2012-06-14 37 views
3

返回參照此SO post添加另一組成遞歸CTE

如果有一個分組類別「類別」,其中,爲了簡單起見,可以是X或Y - 是一件小事修正本腳本這樣它會爲每個類別添加缺失的日期?

我認爲該類別需要添加到CTE中?

換句話說,如果我有以下初始表:

enter image description here

...我怎麼以下幾點:

enter image description here

,很快會上傳我嘗試

我已經調用了初始表#x。我希望能適應遞歸CTE查詢像下面包含的字段類別:

DECLARE @MinDate DATETIME; 
SET @MinDate = (SELECT Min(DATE) FROM #x) 

DECLARE @MaxDate DATETIME; 
SET @MaxDate = (SELECT Max(DATE) FROM #x) 

;WITH times AS 
    ( 
    SELECT @MinDate dt , 1 depth 
    UNION ALL 
    SELECT 
      DATEADD(d, depth, @MinDate) dt 
      , 1 + depth as depth 
    FROM times 
    WHERE DATEADD(d, depth, @MinDate) <= @MaxDate 
    ) 
SELECT 
    * 
FROM 
    TIMES t 
    LEFT OUTER JOIN #X x 
     ON 
     t.dt = x.Date 

好 - 我綁包括CROSS JOIN,但它錯誤地擴大的事:

SELECT DISTINCT Category INTO #Cat FROM #x 

DECLARE @MinDate DATETIME; 
SET @MinDate = (SELECT Min(DATE) FROM #x) 

DECLARE @MaxDate DATETIME; 
SET @MaxDate = (SELECT Max(DATE) FROM #x) 


;WITH times AS 
    ( 
    SELECT 
      Category 
      , @MinDate dt 
      , 1 depth 
    FROM #Cat 
    UNION ALL 
    SELECT 
      c.Category 
      , DATEADD(d, depth, @MinDate) dt 
      , 1 + depth as depth 
    FROM 
      times t 
      CROSS JOIN #Cat c 
       --ON c.Category IS NOT NULL 
    WHERE DATEADD(d, depth, @MinDate) <= @MaxDate 
    ) 
SELECT 
    * 
FROM 
    TIMES 

這似乎已經確定的工作:

SELECT DISTINCT Category INTO #Cat FROM #x 

DECLARE @MinDate DATETIME; 
SET @MinDate = (SELECT Min(DATE) FROM #x) 

DECLARE @MaxDate DATETIME; 
SET @MaxDate = (SELECT Max(DATE) FROM #x) 


;WITH times AS 
    ( 
    SELECT 
      Category 
      , @MinDate dt 
      , 1 depth 
    FROM #Cat 
    UNION ALL 
    SELECT 
      Category 
      , DATEADD(d, depth, @MinDate) dt 
      , 1 + depth as depth 
    FROM 
      times t 
    WHERE DATEADD(d, depth, @MinDate) <= @MaxDate 
    ) 
SELECT 
    * 
FROM 
    TIMES 

回答

1

這是一個沒有日曆表的解決方案(這是生產中必須的)。你可能在變量中有日期範圍,或者你可以從the_table開始min()和max()。

編輯:較短的版本合併成類別日期範圍代

declare @startdate datetime = '2012-1-1' 
declare @enddate datetime = '2012-1-5' 

; with dates([date], category) as (
    select distinct @startdate, category 
    from the_table 
    union all 
    select dateadd (day, 1, [date]), category 
    from dates 
    where [date] < @enddate 
) 
select dates.date, 
     dates.category, 
     isnull(the_table.amount, 0) Amount 
    from dates 
    left join the_table 
    on dates.date = the_table.date 
    and dates.category = the_table.category 
order by dates.category, dates.date 
option (maxrecursion 0) 

There is live test @ Sql FiddleNew Sql Fiddle

+1

爲小提琴網站+1正如我以前從未見過的那樣!在OP中 - 最後一個查詢在WITH子句中有一個交叉連接;這是一個有效的替代 – whytheq

+0

這是怎麼不起作用? http://sqlfiddle.com/#!3/df6751/6 – whytheq

+0

@whytheq請檢查我的修改答案。因爲您在父查詢中需要它,所以我已將類別放在最初的CTE生成中。我會檢查你的小提琴並回到你身邊。 –

1

像這樣的東西應該做的伎倆:

declare @curDate datetime, @maxDate datetime 
declare @count tinyint 

select @curDate = convert(datetime, '20120101', 112), @maxDate = getdate() 
select @count = 0 

while @curDate < @maxDate 
begin 
    select @count = count(1) from tablename where Category = 'X' and convert(varchar(8), Date, 112) = convert(varchar(8), @curDate, 112) 

    if @count > 0 
    begin 
    insert into tablename 
    select 'X', @curDate, 0 
    end 

    select @curDate = dateadd(dd, 1, @curDate) 
end 
+0

+1 aF爲一個不同的方法,但通過試驗和錯誤我已經懷疑它 - 將代碼添加到OP,因爲你可能會發現一個問題(除MaxRecussions) – whytheq

+0

@whytheq謝謝:) –