看了这个需求同事表示很麻烦,列是动态的,多一天多一个订单类型就多一列,我看了下,这不是sql行转列的节奏么。这个还真没搞过。大家pp这个设计是否合理:
1、模拟数据
2、确定思路,网上看了下动态sql实现,自己想了想好像还需要祭出游标神器,一番调式成功了。没有性能问题啊,呵呵,交货了。跟同事说了下思路,他表示看不惯游标里面嵌套游标。好吧,你自己实现吧,偶是有经验的运用游标,不是乱用,爱用不用。呵呵...
USE [SK_WMS_DB]
GO
/****** Object: StoredProcedure [dbo].[sp_warehouse_sum_byOrderDate] Script Date: 01/15/2014 17:16:50 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[sp_warehouse_sum_byOrderDate]
AS
BEGIN
declare @sql varchar(max)
declare @v_order_flag varchar(10)
declare @v_dt Date
declare @v_report_columnName varchar(60)
--订单类型临时表
SELECT distinct [OrderFlag] INTO #OrderFlag_Info FROM [SK_WMS_DB].[dbo].[Table_Report_Test]
ORDER BY [OrderFlag] DESC
--订单日期临时表
SELECT distinct OrderDT INTO #OrderDT_Info FROM [SK_WMS_DB].[dbo].[Table_Report_Test]
ORDER BY OrderDT
--表头临时表
SELECT CAST(NULL AS DATE) ORDER_DT,
CAST ('' AS varchar(60)) AS REP_COL_NAME,
CAST ('' AS varchar(10)) AS OrderFlag
INTO #REPORT_COLUMN
declare cur_order_flag cursor for select OrderFlag from #OrderFlag_Info
open cur_order_flag
fetch next from cur_order_flag into @v_order_flag
--根据订单类型生成列名
while @@FETCH_STATUS = 0
begin
declare cur_OrderDT cursor for select OrderDT from #OrderDT_Info
open cur_OrderDT
fetch next from cur_OrderDT into @v_dt
--日期+订单类型
while @@FETCH_STATUS = 0
begin
INSERT INTO #REPORT_COLUMN
select @v_dt,
CAST(substring(CONVERT(char(10),@v_dt,102),6,5)+ @v_order_flag as varchar(60)),
@v_order_flag
fetch next from cur_OrderDT into @v_dt
end
close cur_OrderDT
deallocate cur_OrderDT
INSERT INTO #REPORT_COLUMN
select '1901-01-01',CAST(RTRIM(LTRIM(@v_order_flag))+'小计' as varchar(60)),@v_order_flag
fetch next from cur_order_flag into @v_order_flag
end
close cur_order_flag
deallocate cur_order_flag
declare @colText varchar(max)
declare cur_tbl cursor for SELECT REP_COL_NAME FROM #REPORT_COLUMN
WHERE ORDER_DT IS NOT NULL
--返回结果临时表
SELECT CAST ('' AS VARCHAR(255)) AS 仓库名称,
CAST ('' AS VARCHAR(255)) AS 库内区域名称,
CAST ('' AS VARCHAR(255)) AS 物料号码,
CAST ('' AS VARCHAR(255)) AS 品名,
CAST ('' AS VARCHAR(255)) AS 包装
INTO #Result_Report
--循环增加列
open cur_tbl
fetch next from cur_tbl into @v_report_columnName
while @@FETCH_STATUS = 0
begin
SET @colText = RTRIM(LTRIM(@v_report_columnName))
SET @sql = 'ALTER TABLE #Result_Report ADD ['+@colText+'] [numeric](18, 2) default 0'
EXEC(@sql)
fetch next from cur_tbl into @v_report_columnName
end
close cur_tbl
deallocate cur_tbl
--清空临时表记录
DELETE FROM #Result_Report
--开始准备数据,每个仓库循环一次
declare @WareHouse varchar(60)
declare @qty numeric(18,2)
declare cur_data_fill
cursor for SELECT distinct [WareHouseName] FROM [SK_WMS_DB].[dbo].[Table_Report_Test]
--填充记录
open cur_data_fill
fetch next from cur_data_fill into @WareHouse
while @@FETCH_STATUS = 0
begin
insert into #Result_Report (仓库名称,库内区域名称,物料号码,品名,包装)
select @WareHouse,'' 库内区域名称,'' 物料号码,'' 品名,'' 包装
declare cur_sum_qty
cursor for
SELECT REP_COL_NAME,ORDER_DT,OrderFlag FROM #REPORT_COLUMN
WHERE ORDER_DT IS NOT NULL
open cur_sum_qty
fetch next from cur_sum_qty into @v_report_columnName,@v_dt,@v_order_flag
while @@FETCH_STATUS = 0
begin
IF @v_dt <> '1901-01-01'
SELECT @qty = isnull(SUM(t.Qty),0) FROM dbo.Table_Report_Test t
WHERE t.WareHouseName = @WareHouse
AND t.OrderDT = @v_dt
AND t.OrderFlag = @v_order_flag
ELSE
SELECT @qty = isnull(SUM(t.Qty),0) FROM dbo.Table_Report_Test t
WHERE t.WareHouseName = @WareHouse
AND t.OrderFlag = @v_order_flag
SELECT @sql = 'UPDATE #Result_Report SET ['+LTRIM(RTRIM(@v_report_columnName))+'] = '+CAST(@qty AS VARCHAR) +
' WHERE 仓库名称 = '''+@WareHouse+''''
EXEC(@sql)
fetch next from cur_sum_qty into @v_report_columnName,@v_dt,@v_order_flag
end
close cur_sum_qty
deallocate cur_sum_qty
fetch next from cur_data_fill into @WareHouse
end
close cur_data_fill
deallocate cur_data_fill
--返回结果集
SELECT * FROM #Result_Report
END
3、成果:
写在这里自己备忘,也给同行看看还有更好的方法不,可以随便喷...