为动态数据透视查询创建存储过程
Creating a Stored Procedure for a Dynamic Pivot Query
一段时间后,我成功地为我的数据库编写了一个动态数据透视查询。
现在我需要将其转换为存储过程。我直接要求答案,因为我对存储过程的了解很少。
下面是代码,我需要传递的参数在 ('01-01-2018'), ('12-01-2018'), (''04|02''), (''FTE 1'',''FTE2'',''FTE 3'')
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)
SELECT @cols = STUFF(
(
SELECT distinct ',' + QUOTENAME([MONTH])
FROM [MY_DB].[dbo].[ACTUAL_BILLABLE_HEADCOUNT]
WHERE [MONTH] BETWEEN ('01-01-2018') AND ('12-01-2018')
ORDER BY ',' + QUOTENAME([MONTH])
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET @query = 'SELECT ' + @cols + '
FROM
(
SELECT [MONTH],[MONTH END BILLABLE]
FROM [MY_DB].[dbo].[ACTUAL_BILLABLE_HEADCOUNT]
WHERE [CC-LOC] = (''04|02'') AND [FTE/RATE CARD] IN (''FTE 1'',''FTE2'',''FTE 3'')
) x pivot (Sum ([MONTH END BILLABLE]) for [MONTH] in (' + @cols + '))p'
execute(@query)
无需太多修改即可将动态数据透视查询转换为存储过程:)
关键是定义变量以替换要传递到存储过程中的硬编码值。以下是一个工作存储过程(命名为 usp_MonthEndBillableDynamicPivot):
CREATE PROCEDURE usp_MonthEndBillableDynamicPivot(
@MonthFrom datetime,
@MonthTo datetime,
@CC_LOC nvarchar(10),
@FTE_RATE_CARD nvarchar(100)
)
AS
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)
SELECT @cols = STUFF(
(
SELECT distinct ',' + QUOTENAME([MONTH])
FROM [MY_DB].[dbo].[ACTUAL_BILLABLE_HEADCOUNT]
WHERE [MONTH] BETWEEN (@MonthFrom) AND (@MonthTo)
ORDER BY ',' + QUOTENAME([MONTH])
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET @query = 'SELECT ' + @cols + '
FROM
(
SELECT [MONTH],[MONTH END BILLABLE]
FROM [MY_DB].[dbo].[ACTUAL_BILLABLE_HEADCOUNT]
WHERE [CC-LOC] = (''' + @CC_LOC + ''') AND [FTE/RATE CARD] IN (' + @FTE_RATE_CARD + ')
) x pivot (Sum ([MONTH END BILLABLE]) for [MONTH] in (' + @cols + '))p'
execute(@query)
我不得不对您在真实 ACTUAL_BILLABLE_HEADCOUNT table 中的数据类型做出一些假设。出于测试目的,我在自己的测试数据库中创建了以下 table:
create table ACTUAL_BILLABLE_HEADCOUNT(
ID int identity(1,1) not null,
MONTH datetime,
[MONTH END BILLABLE] money,
ACTUAL_BILLABLE_HEADCOUNT int,
[CC-LOC] nvarchar(10),
[FTE/RATE CARD] nvarchar(100),
constraint PK_ACTUAL_BILLABLE_HEADCOUNT primary key(ID)
)
并用以下测试数据填充它(注意我使用 YYYY-MM-DD ISO 日期表示法以减少美国和英国日期(我的位置)之间的混淆)
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-01-01',10000.00,10,'04|02','FTE 1');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-01-01',20000.00,20,'04|02','FTE 2');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-01-01',30000.00,30,'04|02','FTE 3');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-01-01',40000.00,40,'04|02','FTE 4');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-02-01',10000.00,10,'04|02','FTE 1');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-02-01',20000.00,20,'04|02','FTE 2');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-02-01',30000.00,30,'04|02','FTE 3');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-02-01',40000.00,40,'04|02','FTE 4');
请注意我已经包含了一个额外的 'FTE 4' 值,我用它来检查所有这些的动态性质!
具备以上条件,就可以执行存储过程了:
declare
@MonthFrom datetime = '2018-01-01',
@MonthTo datetime = '2018-12-01',
@CC_LOC nvarchar(10) = '04|02',
@FTE_RATE_CARD nvarchar(100) = '''FTE 1'',''FTE2'',''FTE 3'',''FTE 4'''
;
exec usp_MonthEndBillableDynamicPivot @MonthFrom, @MonthTo, @CC_LOC, @FTE_RATE_CARD;
结果如下:
希望对您有所帮助!
一段时间后,我成功地为我的数据库编写了一个动态数据透视查询。 现在我需要将其转换为存储过程。我直接要求答案,因为我对存储过程的了解很少。 下面是代码,我需要传递的参数在 ('01-01-2018'), ('12-01-2018'), (''04|02''), (''FTE 1'',''FTE2'',''FTE 3'')
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)
SELECT @cols = STUFF(
(
SELECT distinct ',' + QUOTENAME([MONTH])
FROM [MY_DB].[dbo].[ACTUAL_BILLABLE_HEADCOUNT]
WHERE [MONTH] BETWEEN ('01-01-2018') AND ('12-01-2018')
ORDER BY ',' + QUOTENAME([MONTH])
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET @query = 'SELECT ' + @cols + '
FROM
(
SELECT [MONTH],[MONTH END BILLABLE]
FROM [MY_DB].[dbo].[ACTUAL_BILLABLE_HEADCOUNT]
WHERE [CC-LOC] = (''04|02'') AND [FTE/RATE CARD] IN (''FTE 1'',''FTE2'',''FTE 3'')
) x pivot (Sum ([MONTH END BILLABLE]) for [MONTH] in (' + @cols + '))p'
execute(@query)
无需太多修改即可将动态数据透视查询转换为存储过程:)
关键是定义变量以替换要传递到存储过程中的硬编码值。以下是一个工作存储过程(命名为 usp_MonthEndBillableDynamicPivot):
CREATE PROCEDURE usp_MonthEndBillableDynamicPivot(
@MonthFrom datetime,
@MonthTo datetime,
@CC_LOC nvarchar(10),
@FTE_RATE_CARD nvarchar(100)
)
AS
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)
SELECT @cols = STUFF(
(
SELECT distinct ',' + QUOTENAME([MONTH])
FROM [MY_DB].[dbo].[ACTUAL_BILLABLE_HEADCOUNT]
WHERE [MONTH] BETWEEN (@MonthFrom) AND (@MonthTo)
ORDER BY ',' + QUOTENAME([MONTH])
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET @query = 'SELECT ' + @cols + '
FROM
(
SELECT [MONTH],[MONTH END BILLABLE]
FROM [MY_DB].[dbo].[ACTUAL_BILLABLE_HEADCOUNT]
WHERE [CC-LOC] = (''' + @CC_LOC + ''') AND [FTE/RATE CARD] IN (' + @FTE_RATE_CARD + ')
) x pivot (Sum ([MONTH END BILLABLE]) for [MONTH] in (' + @cols + '))p'
execute(@query)
我不得不对您在真实 ACTUAL_BILLABLE_HEADCOUNT table 中的数据类型做出一些假设。出于测试目的,我在自己的测试数据库中创建了以下 table:
create table ACTUAL_BILLABLE_HEADCOUNT(
ID int identity(1,1) not null,
MONTH datetime,
[MONTH END BILLABLE] money,
ACTUAL_BILLABLE_HEADCOUNT int,
[CC-LOC] nvarchar(10),
[FTE/RATE CARD] nvarchar(100),
constraint PK_ACTUAL_BILLABLE_HEADCOUNT primary key(ID)
)
并用以下测试数据填充它(注意我使用 YYYY-MM-DD ISO 日期表示法以减少美国和英国日期(我的位置)之间的混淆)
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-01-01',10000.00,10,'04|02','FTE 1');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-01-01',20000.00,20,'04|02','FTE 2');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-01-01',30000.00,30,'04|02','FTE 3');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-01-01',40000.00,40,'04|02','FTE 4');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-02-01',10000.00,10,'04|02','FTE 1');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-02-01',20000.00,20,'04|02','FTE 2');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-02-01',30000.00,30,'04|02','FTE 3');
insert into ACTUAL_BILLABLE_HEADCOUNT([MONTH],[MONTH END BILLABLE],ACTUAL_BILLABLE_HEADCOUNT,[CC-LOC],[FTE/RATE CARD])
values ('2018-02-01',40000.00,40,'04|02','FTE 4');
请注意我已经包含了一个额外的 'FTE 4' 值,我用它来检查所有这些的动态性质!
具备以上条件,就可以执行存储过程了:
declare
@MonthFrom datetime = '2018-01-01',
@MonthTo datetime = '2018-12-01',
@CC_LOC nvarchar(10) = '04|02',
@FTE_RATE_CARD nvarchar(100) = '''FTE 1'',''FTE2'',''FTE 3'',''FTE 4'''
;
exec usp_MonthEndBillableDynamicPivot @MonthFrom, @MonthTo, @CC_LOC, @FTE_RATE_CARD;
结果如下:
希望对您有所帮助!