在动态数据透视上包含默认值

时间:2013-02-27 19:46:28

标签: sql sql-server pivot

我基于日期在表中转移数据,但是对于没有数据的日期需要返回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返回的结果集:

Pivot data

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

感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

然后你真的不需要动态生成这些列,因为你总是想要它们从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;