【问题标题】:Including default values on dynamic pivot包括动态透视的默认值
【发布时间】:2013-02-27 19:46:28
【问题描述】:

我正在根据日期对表中的数据进行透视,但需要为没有数据的日期返回 NULL。

[dbo].[Metrics] 中的数据:

我正在执行的动态数据透视 SQL:

DECLARE @cols NVARCHAR(1000);
SELECT @cols = 
STUFF((SELECT N'],[' + month_day
         FROM (SELECT DISTINCT RIGHT(CONVERT(NCHAR(10), [Date], 126), 2)
                 FROM [Metrics]) AS O(month_day)
         ORDER BY month_day
          FOR XML PATH('')
       ), 1, 2, '') + N']';

DECLARE @sql NVARCHAR(2000);

SET @sql =
N'SELECT [Key], ' + @cols +
N'  FROM (SELECT [Key], ' +
N'               RIGHT(CONVERT(NCHAR(10), [Date], 126), 2) AS month_day, ' +
N'               [Value] ' +
N'          FROM [Metrics]) AS O ' +
N'PIVOT ' +
N'(SUM([Value]) FOR month_day IN (' + @cols + N')) AS P;';

EXECUTE(@sql);

...以及动态SQL返回的结果集:

如您所见,由于我没有每月每一天的数据,因此根本不会返回那些日子的列。如何让它为每个单元格返回 NULL 列 10-23 和 28-31?无论实际月份如何,它都应返回第 1-31 列(例如,即使给定月份少于 31 天,也应返回 31 列)。

感谢任何帮助。

【问题讨论】:

    标签: sql sql-server pivot


    【解决方案1】:

    那么您实际上并不需要动态生成这些列,因为您总是希望它们从 1 到 31。更简单的方法是在您的枢轴上硬编码这些值,真的。无论如何,这是您可以动态定义列并且仍然可以得到所有天数的方式:

    SELECT @cols = 
    STUFF((SELECT N'],[' + CAST(number AS VARCHAR(2))
             FROM (SELECT DISTINCT number
                   FROM master..[spt_values] 
                   WHERE number BETWEEN 1 AND 31) AS O(number)
             ORDER BY number
              FOR XML PATH('')
           ), 1, 2, '') + N']';
    

    你真正应该使用的版本是这样的:

    SELECT *
    FROM (SELECT [Key], 
                 RIGHT(CONVERT(NCHAR(10), [Date], 126), 2) AS month_day, 
                 [Value] 
          FROM [Metrics]) AS O 
    PIVOT (SUM([Value]) FOR month_day IN ([01],[02],[03],[04],[05],[06],[07],[08],[09],
                                          [10],[11],[12],[13],[14],[15],[16],[17],[18],
                                          [19],[20],[21],[22],[23],[24],[25],[26],[27],
                                          [28],[29],[30],[31])) AS P;
    

    【讨论】:

    • 嗨 Lamak,感谢您的提示。我非常专注于使用动态 SQL,我并没有停下来想也许我不需要。我实现了您的第二个解决方案,它几乎可以完美运行,except 它似乎没有返回第 1-9 天的值。我想这与 RIGHT() 函数和前导零有关,对吗?
    • @PhillipCopley 是的,对不起,你说得对。更新了我的答案。
    猜你喜欢
    • 2020-04-07
    • 1970-01-01
    • 2013-11-05
    • 1970-01-01
    • 2014-01-30
    • 2018-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多