【问题标题】:Dynamic SQL Rolling 12 Months Pivot动态 SQL 滚动 12 个月数据透视
【发布时间】: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'等,但这不起作用

【问题讨论】:

    标签: sql sql-server pivot dynamic-sql


    【解决方案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/…
    猜你喜欢
    • 1970-01-01
    • 2013-10-06
    • 1970-01-01
    • 2019-01-04
    • 1970-01-01
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    • 2019-11-26
    相关资源
    最近更新 更多