2017-07-07 8 views
1

1つのscdタイプ2ディメンションに対して、時間間隔が重複しているレコードの特定と修正に1つの問題があります。 は私が持っていることは次のとおりです。1つのタイプ2のSCDディメンションから重複する時間間隔を確認する方法

Bkey Uid startDate      endDate 
'John' 1 1990-01-01 (some time stamp) 2017-01-10 (some time stamp) 
'John' 2 2016-11=03 (some time stamp) 2016-11-14 (some time stamp) 
'John' 3 2016-11-14 (some time stamp) 2016-12-29 (some time stamp) 
'John' 4 2016-12-29 (some time stamp) 2017-01-10 (some time stamp) 
'John' 5 2017-01-10 (some time stamp) 2017-04-22 (some time stamp) 
...... 

は私がである(最初の)見つけたいすべてのジョンズ・テーブルがたくさんジョンズの多くを持つし、それらの重複を修正する方法を把握するためのオーバーラップ期間を有します期間。最新の情報としては、LAGG、LEADの機能がありますが、それを扱うことができますが、それを使ってそれらを見つける方法がわかりません。 ヒント? よろしく、

+0

これを修正するには:原子ごとの間隔(1日)、DISTINCT、島を検索します。 – Serg

+0

@Groupsテーブル変数の宣言で[Edit 1]セクションを追加しました。 –

答えて

1

[1]重複した時間を返しますクエリに続いて、範囲:

SELECT *, 
     (
      SELECT * 
      FROM @Dimension1 y 
      WHERE x.Bkey = y.Bkey 
      AND  x.Uid <> y.Uid 
      AND  NOT(x.startDate > y.endDate OR x.endDate < y.startDate) 
      FOR XML RAW, ROOT, TYPE 
     ) OverlappingTimeRanges 
FROM @Dimension1 x 

全スクリプト:

DECLARE @Dimension1 TABLE (
    Bkey  VARCHAR(50) NOT NULL, 
    Uid   INT NOT NULL, 
    startDate DATE NOT NULL, 
    endDate  DATE NOT NULL, 
     CHECK(startDate < endDate) 
); 
INSERT @Dimension1 
SELECT 'John', 1, '1990-01-01', '2017-01-10' UNION ALL 
SELECT 'John', 2, '2016-11-03', '2016-11-14' UNION ALL 
SELECT 'John', 3, '2016-11-14', '2016-12-29' UNION ALL 
SELECT 'John', 4, '2016-12-29', '2017-01-10' UNION ALL 
SELECT 'John', 5, '2017-01-11', '2017-04-22'; 

SELECT *, 
     (
      SELECT * 
      FROM @Dimension1 y 
      WHERE x.Bkey = y.Bkey 
      AND  x.Uid <> y.Uid 
      AND  NOT(x.startDate > y.endDate OR x.endDate < y.startDate) 
      FOR XML RAW, ROOT, TYPE 
     ) OverlappingTimeRanges 
FROM @Dimension1 x 

Demo here

[2]時間の異なるグループを見つけるために重複する元の行の範囲私は以下のアプローチを使用します:

-- Edit 1 
DECLARE @Groups TABLE (
    Bkey   VARCHAR(50) NOT NULL, 
    Uid    INT NOT NULL, 
    startDateNew DATE NOT NULL, 
    endDateNew  DATE NOT NULL, 
     CHECK(startDateNew < endDateNew) 
); 
INSERT @Groups 
SELECT x.Bkey, x.Uid, z.startDateNew, z.endDateNew 
FROM @Dimension1 x 
OUTER APPLY (
    SELECT MIN(y.startDate) AS startDateNew, MAX(y.endDate) AS endDateNew 
    FROM @Dimension1 y 
    WHERE x.Bkey = y.Bkey 
    AND  NOT(x.startDate > y.endDate OR x.endDate < y.startDate) 
) z 
-- End of Edit 1 

-- This returns distinct groups identified by DistinctGroupId together with all overlapping Uid(s) from current group 
SELECT * 
FROM (
    SELECT ROW_NUMBER() OVER(ORDER BY b.Bkey, b.startDateNew, b.endDateNew) AS DistinctGroupId, b.* 
    FROM (
     SELECT DISTINCT a.Bkey, a.startDateNew, a.endDateNew 
     FROM @Groups a 
    ) b 
) c 
OUTER APPLY (
    SELECT d.Uid AS Overlapping_Uid 
    FROM @Groups d 
    WHERE c.Bkey = d.Bkey 
    AND  c.startDateNew = d.startDateNew 
    AND  c.endDateNew = d.endDateNew 
) e 

-- This returns distinct groups identified by DistinctGroupId together with an XML (XmlCol) which includes overlapping Uid(s) 
SELECT * 
FROM (
    SELECT ROW_NUMBER() OVER(ORDER BY b.Bkey, b.startDateNew, b.endDateNew) AS DistinctGroupId, b.* 
    FROM (
     SELECT DISTINCT a.Bkey, a.startDateNew, a.endDateNew 
     FROM @Groups a 
    ) b 
) c 
OUTER APPLY (
    SELECT (
    SELECT d.Uid AS Overlapping_Uid 
    FROM @Groups d 
    WHERE c.Bkey = d.Bkey 
    AND  c.startDateNew = d.startDateNew 
    AND  c.endDateNew = d.endDateNew 
    FOR XML RAW, TYPE 
    ) AS XmlCol 
) e 

enter image description here

注:私の例で使用される最後の範囲は'John', 5, '2017-01-11', '2017-04-22';ない'John', 5, '2017-01-10', '2017-04-22';です。また、使用されるデータタイプはDATEであり、DATETIME[2][OFFSET]ではありません。

0

質問のトリッキーな部分は、範囲が重複するためのロジックを明確にすることができると思います。左側の行が右側の行と重なっているという条件に自己結合することができます。一致するすべての行は、重複する行です。

我々は四つの可能なオーバーラップシナリオを考えることができます。

|---------| |---------| no overlap 

|---------| 
     |---------|   1st end and 2nd start overlap 

     |---------| 
|---------|     1st start and 2nd end overlap 

|---------| 
    |---|     2nd completely contained inside 1st 
          (could be 1st inside 2nd also) 

SELECT DISTINCT 
    t.Uid 
FROM yourTable t1 
INNER JOIN yourTable t2 
    ON t1.startDate <= t2.endDate AND 
     t2.startDate <= t1.endDate 
WHERE 
    t1.Bkey = 'John' AND t2.Bkey = 'John' 

これは、少なくともあなたは、重複レコードを識別できるようになります。意味のあるやり方でそれらを更新して分離することは、おそらく別の疑問に遭うかもしれない醜いギャップや島の問題に終わるでしょう。

+2

[overlaps tag wiki](https://stackoverflow.com/tags/overlap/info)を見てください。重複した要素の最も簡単なテストが可能です。 –

関連する問題