我基于日期在表中转移数据,但是对于没有数据的日期需要返回NULL。
[dbo]中的数据。[指标]:
我正在执行的动态数据透视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返回的结果集:
正如您所看到的,由于我没有每月每天的数据,因此根本不会返回那些日子的列。如何让每个单元格返回10-23和28-31列为NULL?无论实际月份如何,它都应返回1-31列(例如,即使在给定月份中少于31天,也会返回31列。)
感谢任何帮助。
答案 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;