2013-02-27 34 views
0

我將基於日期的數據轉換爲表格,但需要在沒有數據的日期返回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

由於喲你可以看到,因爲我沒有每月的每一天的數據,它根本就不會返回那些日子的列。我怎樣才能讓它返回每個單元格爲NULL的列10-23和28-31?無論實際月份如何,它都應該返回第1-31列(例如,即使在特定月份中少於31天的情況下也是31列)。

任何幫助表示讚賞。

回答

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; 
+0

嗨Lamak,用於尖端的感謝。我非常專注於使用動態SQL,我並沒有停下來想,也許我不需要。我實現了你的第二個解決方案,它的工作幾乎完美,除了1-9天似乎沒有返回值。我想這與RIGHT()函數有關,而且這個前導零是正確的? – 2013-02-27 20:04:48

+0

@PhillipCopley是的,對不起,你對此是正確的。更新了我的答案。 – Lamak 2013-02-27 20:08:36