动态 SQL 滚动 12 个月数据透视
Posted
技术标签:
【中文标题】动态 SQL 滚动 12 个月数据透视【英文标题】:Dynamic SQL Rolling 12 Months Pivot 【发布时间】:2021-08-09 13:03:53 【问题描述】:我是动态 SQL 的新手。我有下表:
CustName | Date | Hours |
---|---|---|
First | 01/01/2021 | 12 |
Second | 01/01/2021 | 10 |
Second | 05/02/2021 | 1 |
Second | 10/11/2021 | 14 |
我正在尝试为过去 12 个月的总小时数制作一个滚动日历 Pivot。
这是我做的代码:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF(
(SELECT distinct ',' + QUOTENAME(DATENAME(mm,Date) + ' of '
+ DATENAME(year,Date)) AS months_ago
FROM [TimeEntryList]
WHERE Date > DATEADD(year, -1,
DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1))
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT CustName, ' + @cols + '
from ( select
[CustName],
datename(mm,[Date])+'' of ''+datename(year,[Date])AS
months_ago, [Hours] AS NetQty
from [TimeEntryList]
WHERE [Date] > DATEADD(year, -1,
DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1))
) as source
pivot
(
sum(NetQty) For months_ago in (' + @cols + ')
) as PivotTable'
execute sp_executesql @query;
这“有点”我想要的效果,但列不是从当前日期倒序排列的。
我希望它从当前月份开始倒数。因此,如果这个月是 8 月,那将是:
CustName | Sep 2020 | .... months | August 2021 |
---|---|---|---|
First | 12 | 14 | |
Second | 3 | 12 |
有没有一种好方法可以从 Dynamic SQL 中的当前月份开始,然后返回 12 个月?
我试过'order by months_ago desc'等,但这不起作用
【问题讨论】:
【参考方案1】:您只需要添加一个WHERE
过滤器。这需要在查询的两个部分中。
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
SET @cols = STUFF(
(SELECT ',' + QUOTENAME(DATENAME(mm, EOMONTH(Date)) + ' of ' + DATENAME(year, EOMONTH(Date))) AS months_ago
FROM [TimeEntryList]
WHERE [Date] > DATEADD(year, -1, DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1))
GROUP BY EOMONTH(Date)
ORDER BY EOMONTH(Date)
FOR XML PATH(''), TYPE
).value('text()[1]', 'NVARCHAR(MAX)')
,1,1,'');
SET @query = '
SELECT
CustName,
' + @cols + '
from (
select
[CustName],
datename(mm,[Date])+'' of ''+datename(year,[Date])AS months_ago, [Hours] AS
NetQty
from [TimeEntryList]
WHERE [Date] > DATEADD(year, -1, DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1))
) as source
pivot
(
sum(NetQty) For months_ago in (' + @cols + ')
) as PivotTable;
';
execute sp_executesql @query;
您甚至可以传递开始日期参数,如下所示:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@dateFrom datetime;
SET @dateFrom = DATEADD(year, -1, DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1));
SET @cols = STUFF(
(SELECT ',' + QUOTENAME(DATENAME(mm,EOMONTH(Date)) + ' of ' + DATENAME(year,EOMONTH(Date)) AS months_ago
FROM [TimeEntryList]
WHERE [Date] > @dateFrom
GROUP BY EOMONTH(Date)
ORDER BY EOMONTH(Date)
FOR XML PATH(''), TYPE
).value('text()[1]', 'NVARCHAR(MAX)')
,1,1,'');
SET @query = '
SELECT
CustName,
' + @cols + '
from (
select
[CustName],
datename(mm,[Date])+'' of ''+datename(year,[Date])AS months_ago, [Hours] AS
NetQty
from [TimeEntryList]
WHERE [Date] > @dateFrom
) as source
pivot
(
sum(NetQty) For months_ago in (' + @cols + ')
) as PivotTable;
';
execute sp_executesql
@query
N'@dateFrom datetime',
@dateFrom = @dateFrom;
【讨论】:
啊-谢谢。出于某种原因,我得到的 'QUOTENAME' 不是内置函数。如果我将它括在括号中,它会修复它,但报告只是执行并且不显示数据。 我编辑了我的答案,谢谢!我认为主要问题是,我试图将最后一列作为当前月份,列按月向后滚动 我认为归结为“动态”部分的排序。我知道如何在常规 SQL 中按日期排序,但是对于这个动态示例,我认为我需要尝试在“months_ago”上进行排序,但这是行不通的。也许我需要先创建一个临时数据透视表,然后使用动态 SQL ...也许 .. 有点新。 谢谢! - 我创建了一个here 如您所见,2021 年 4 月首先出现。 OK 为你解决了这个问题dbfiddle.uk/…以上是关于动态 SQL 滚动 12 个月数据透视的主要内容,如果未能解决你的问题,请参考以下文章