2017-03-08 66 views
0

我有一個要求填寫數據中缺失的時間間隔,並填充Cnt列爲0的任何間隙。我需要爲此使用日曆表嗎?問:TSQL - 在數據中添加缺失的年月差距?

我的查詢結果已經彙總,我只需要添加空白。

select name 
     ,YR 
     ,MO 
     ,[Cnt] 
from dbo.OON 

電流輸出:

Name | YR | MO | Cnt 
Kelly | 2014 | 1 | 197 
Kelly | 2014 | 3 | 200 
Kelly | 2014 | 5 | 300 
Kelly | 2015 | 2 | 100 
Kelly | 2015 | 3 | 50 
Kelly | 2015 | 6 | 70 

所需的輸出:

Name | YR | MO | Cnt 
Kelly | 2014 | 1 | 197 
Kelly | 2014 | 2 | 0 
Kelly | 2014 | 3 | 200 
Kelly | 2014 | 4 | 0 
Kelly | 2014 | 5 | 300 
Kelly | 2014 | 6 | 0 
Kelly | 2014 | 7 | 0 
Kelly | 2014 | 8 | 0 
Kelly | 2014 | 9 | 0 
Kelly | 2014 | 10 | 0 
Kelly | 2014 | 11 | 0 
Kelly | 2014 | 12 | 0 
Kelly | 2015 | 1 | 0 
Kelly | 2015 | 2 | 100 
Kelly | 2015 | 3 | 50 
Kelly | 2015 | 4 | 0 
Kelly | 2015 | 5 | 0 
Kelly | 2015 | 6 | 70 
Kelly | 2015 | 7 | 0 
Kelly | 2015 | 8 | 0 
Kelly | 2015 | 9 | 0 
Kelly | 2015 | 10 | 0 
Kelly | 2015 | 11 | 0 
Kelly | 2015 | 12 | 0 
+1

是的,我通常用日曆表做這件事。您可以在查詢時遞歸生成一個,但最好的選擇是創建一個持久化的並將其存儲在數據倉庫中。如果您正在尋找可視化,Power BI將是一個不錯的選擇,您可以使用'CALENDARAUTO()'在DAX中生成日曆。 – smj

+0

這是一篇好文章:https://www.mssqltips.com/sqlservertip/4054/creating-a-date-dimension-or-calendar-table-in-sql-server/ – smj

回答

2

另一種選擇是一個特設的理貨表

Declare @OON table (Name varchar(25),YR int,MO int,Cnt int) 
Insert Into @OON values 
('Kelly' , 2014 , 1 , 197), 
('Kelly' , 2014 , 3 , 200), 
('Kelly' , 2014 , 5 , 300), 
('Kelly' , 2015 , 2 , 100), 
('Kelly' , 2015 , 3 , 50), 
('Kelly' , 2015 , 6 , 70) 

Declare @PerBeg date = '2014-01-01' 
Declare @Months int = 24 

Select B.Name 
     ,Yr=Year(A.D) 
     ,MO=Month(A.D) 
     ,Cnt=IsNull(C.Cnt,0) 
From (Select Top (@Months) D=DateAdd(MM,-1+Row_Number() Over (Order By (Select null)),@PerBeg) From master..spt_values) A 
Cross Join (Select Distinct Name from @OON) B 
Left Join @OON C on B.Name=C.Name and Year(A.D)=C.Yr and Month(A.D)=C.MO 

返回

Name Yr  MO Cnt 
Kelly 2014 1 197 
Kelly 2014 2 0 
Kelly 2014 3 200 
Kelly 2014 4 0 
Kelly 2014 5 300 
Kelly 2014 6 0 
Kelly 2014 7 0 
Kelly 2014 8 0 
Kelly 2014 9 0 
Kelly 2014 10 0 
Kelly 2014 11 0 
Kelly 2014 12 0 
Kelly 2015 1 0 
Kelly 2015 2 100 
Kelly 2015 3 50 
Kelly 2015 4 0 
Kelly 2015 5 0 
Kelly 2015 6 70 
Kelly 2015 7 0 
Kelly 2015 8 0 
Kelly 2015 9 0 
Kelly 2015 10 0 
Kelly 2015 11 0 
Kelly 2015 12 0 
0

你可以有一個永久的日曆表,或者你可以逃脫正常的Numbers表格。無論哪種方式,建立一個遞歸cte是更可取的解決方案。但是,如果是一次性的報告,您可以輕鬆地擺脫簡單的CTE,就像每下面:

;with n as (
    select 1 as n 
    UNION ALL 
    SELECT n + 1 FROM n WHERE n < 20), 
years as (
    select 2013 + n.n as [year] from n where n < 3), 
months as (
    select 0 + n.n as [month] from n where n < 13) 
select r.name, years.[year], months.[month], coalesce(r.Cnt,0) 
from years cross join months 
left join dbo.OON r on years.[year] = r.[YR] and months.[month] = r.[MO] 
order by 1,2,3 

在上面的查詢,你不妨用初值爲years CTE和數量今年作爲參數

+0

遞歸CTE的執行效率會低得多而不是John在上面發佈的理貨表解決方案。請注意這篇優秀的文章:http://www.sqlservercentral.com/articles/T-SQL/74118/ –