3

この質問は、この SO 投稿に関連しています

再帰的な CTE を使用するのではなく、DimDates テーブルを使用して欠落しているデータ (日付によって欠落していると見なされる) を追加するにはどうすればよいですか?

次の2つのテーブルがあります。

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')

これらは私が達成しようとしている結果です。ウェアハウスの DimDate テーブルを使用すると、ロードが簡単になると誤って想定したため、再帰的な CTE を気にしたことはありません。

ここに画像の説明を入力

わかりました-可能な解決策に出くわした可能性があります-間違っている場合は、次の穴を開けてください:

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

これが私が最終的に得たものです。マークされた回答とアーロンの投稿の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] 
            ) 
4

4 に答える 4

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

データ ウェアハウスを作成している場合は、カテゴリをディメンション テーブルに入れることをお勧めします。

于 2012-06-20T15:59:18.553 に答える
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;
于 2012-06-20T16:10:41.660 に答える
1

可能な解決策を示す明らかに悪い疑似コード

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

これは、テーブル 1 にデータを追加しようとしていると仮定しています。

記憶に残したいだけなら、

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

または単なる外部結合

于 2012-06-20T15:56:47.647 に答える
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)
于 2012-06-20T15:59:09.363 に答える