2017-03-08 2 views
0

Ich habe eine Anforderung, die fehlenden Zeitlücken in den Daten auszufüllen und die Spalte Cnt für Lücken mit 0 zu füllen. Muss ich dafür eine Kalendertabelle verwenden?F: TSQL - Füge fehlende Jahrs- und Monatslücken in Daten hinzu?

Die Ergebnisse meiner Abfrage sind bereits aggregiert, ich muss nur die Lücken hinzufügen.

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

Stromausgang:

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 

gewünschte Ausgabe:

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

Ja, normalerweise mache ich das mit einer Kalender Tabelle. Sie können einen rekursiv zur Abfragezeit generieren, die beste Option besteht jedoch darin, einen dauerhaften Wert zu erstellen und in Ihrem Data Warehouse zu speichern. Wenn Sie dies visualisieren möchten, wäre Power BI eine gute Option. Sie können den Kalender in DAX mit 'CALENDARAUTO()' erstellen. – smj

+0

Hier ist ein guter Artikel: https://www.mssqltips.com/sqlservertip/4054/creating-a-date-dimension-dimension-calendar-table-in-sql-server/ – smj

Antwort

2

eine weitere Option ist ein ad-hoc-tally Tabelle

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 

Returns

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

Sie könnten einen permanenten Kalender Tabelle haben, oder Sie können mit einem normalen Zahlen Tisch weg. In jedem Fall ist es besser, eine rekursive CTE zu erstellen. Wenn es jedoch ein einmaliger Bericht ist, kann man leicht mit einem einfachen CTE weg, wie nach dem unten angegebenen:

;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 

In der Abfrage über Du den Anfangswert für die years CTE und die Anzahl verwenden möchtest des Jahres als Parameter

+0

Ein rekursive CTE wird viel weniger effizient als die Tally-Table-Lösung, die John oben gepostet hat. Beachten Sie diesen ausgezeichneten Artikel: http://www.sqlservercentral.com/articles/T-SQL/74118/ –

Verwandte Themen