2012-06-20 39 views
3

添加這個問題是關係到this SO post使用生產日期表中缺少的行

而不是使用遞歸CTE如何添加缺失數據(經認定失蹤日期)使用DimDates表?

我有以下兩個表:

create table the_table 
(
    [Date] datetime, 
    Category2 varchar(10), 
    Amount INT 
) 
insert into the_table 
values 
('01 jan 2012', 'xx', 10), 
('03 jan 2012', 'yy', 50) 


create table DimDate 
(
    [Date] datetime 
) 
insert into DimDate 
values 
('01 jan 2012'), 
('02 jan 2012'), 
('03 jan 2012'), 
('04 jan 2012') 

這些是我想要得到的結果。我沒有用遞歸CTE困擾我,錯誤地認爲,它會使用我們的倉庫DimDate表是負載更容易:

enter image description here

好的 - 我可能會在一個可能的解決方案偶然 - 請戳孔在下面,如果它是錯誤的:

select 

    coalesce(x.[Date], y.[Date]) AS Date , 
    coalesce(x.Category2, y.Category2) AS Category2 , 
    isnull(Amount,0) as Amount 
from the_table x 
full outer join 
(
select 
    d.Date 
    , t.Category2 
from 
     the_table t 
     cross join DimDate d 
) y 
    on 
    x.Category2 = y.Category2 
    and 
    x.Date = y.Date 

這就是我已經結束了。標記答案的組合AMD的CTE從亞倫的帖子:

;WITH 
    Dates_cte ([Date]) AS 
      (
      SELECT [Date] = DayMarker 
      FROM WHData.dbo.vw_DimDate x 
      WHERE 
        x.DayMarker >= (SELECT MIN([Date]) FROM #Data1 WHERE Period = 'Daily') AND 
        x.DayMarker <= GETDATE() 
      ) 
    ,Categories ([Operator], [Market], [Product], [Measure]) AS 
       ( 
       SELECT DISTINCT 
         [Operator] 
         , [Market] 
         , [Product] 
         , [Measure] 
       FROM #Data1 
       WHERE [Period] = 'Daily' 
       ) 
INSERT INTO #Data1 
    SELECT 
     c.[Operator] 
     , c.[Market] 
     , c.[Product] 
     , [Period] = CONVERT(VARCHAR(100), 'Daily') 
     , d.[Date] 
     , c.[Measure] 
     , 0 
    FROM Dates_cte d CROSS JOIN Categories c 
    WHERE NOT EXISTS 
      ( 
      SELECT * 
      FROM #Data1 AS T 
      WHERE 
        t.[Period] = 'Daily' AND 
        t.[Operator] = c.[Operator] AND 
        t.[Market] = c.[Market] AND 
        t.[Product] = c.[Product] AND 
        t.[Measure] = c.[Measure] AND 
        t.[Date] = d.[Date] 
      ) 
+0

'CROSS JOIN'做同樣的事情嗎? - 我補充說的是獲得笛卡爾產品 – whytheq

+0

nah - 'CROSS JOIN'不是我用過的;所以你的評論是有效的 - 我將編輯OP – whytheq

+0

在你的問題你想'添加'缺少的行。從你的編輯中,我猜你只是在選擇時而不是插入缺失的行?如果是這樣,這是一個簡單得多的模板'SELECT dates.date,categories.category,ISNULL(data.val,0)FROM日期CROSS JOIN類別LEFT JOIN數據ON data.date = dates.date AND data.category = categories。 *** [不是每件事都需要一個完整的外部聯接。] *** – MatBailie

回答

3

使用INSERT INTO ... SELECT FROM DimDate CROSS JOIN categories WHERE NOT EXISTS ...

試試這個:

INSERT INTO the_table 
([Date], Category2, Amount) 
SELECT [Date], category2, 0 
FROM DimDate 
CROSS JOIN 
(
    SELECT DISTINCT category2 FROM the_table 
) AS categories 
WHERE NOT EXISTS 
(
    SELECT * 
    FROM thetable AS T 
    WHERE T.category2 = categories.Category2 
    AND T.[Date] = DimDate.[Date] 
) 

看到它聯機工作:ideone

如果您要創建一個數據倉庫,我建議你把類別爲維度表。

+0

+1:尤其是對於建議類別維度表。 – MatBailie

+0

可愛的腳本。我只是使用WH--而不是創建它。 – whytheq

+0

Mark - 在OP Dems的評論中提到,由於數據爆炸,我使用CROSS JOIN的可能解決方案效率低下....您使用的CROSS JOIN有什麼不同?它同樣效率低下嗎? – whytheq

1

顯然不好的僞代碼,顯示了可能的解決方案

insert into table1 
    select from table2 
     where not exists (select from table1 where table1.date = table2.date) 

這假設您tyring將數據添加到表1

如果你只是想在內存中,

select * from table 1 
union 
select * from table 2 where not exists (select from table1 where table1.date = table2.date) 

或只是一個外部聯接

+0

缺少'Category2'部分 –

+0

@aF。與馬克拜爾斯相比,回答這肯定是邏輯的好開始 – whytheq

+0

@whytheq是的,我沒有說任何其他的想法:) –

0

步驟1,插入缺少日期:

select [Date], '', 0 from DimDate 
where [Date] not in (select [Date] from the_table) 

步驟2,更新Categoriy2柱:

update the_table 
set Category2 = 
    (select aux.Category from the_table aux where t.Date = 
     (select max(t.Date) from the_table t 
     where t.Category2 <> '' and t.Date < aux.Date) 
1
;WITH cat AS (SELECT Category2 FROM the_table GROUP BY Category2) 
INSERT the_table([Date], Category2, Amount) 
SELECT d.[Date], cat.Category2, 0 
FROM DimDate AS d CROSS JOIN cat 
LEFT OUTER JOIN the_table AS t 
ON d.[Date] = t.[Date] 
AND cat.Category2 = t.Category2 
WHERE t.[Date] IS NULL; 
+0

已關閉主題: - 剛剛檢查[本文出](http://sqlblog.com/blogs/aaron_bertrand/archive/2008/10/30/my-stored-procedure-best-practices-checklist.aspx)希望我再讀一遍吧! – whytheq