2011-12-28 18 views
-1
TableA (
    id int, 
    match1 char, 
    match2 char, 
    startdate datetime, 
    enddate, 
    status char 
) 

サンプルデータ:SQL Serverの:同じテーブル内の重複日付

id match1 match2 startdate enddate  Status 
1 AAA  BBB  2006-01-01 2007-01-01 
2 AAA  BBB  2006-12-12 2008-01-01 
3 AAA  BBB  2008-01-01 2012-02-02 
4 AAA  BBB  2002-01-01 2004-01-01 
5 DDD  EEE  2009-01-01 2012-01-01 
6 DDD  EEE  2011-01-01 2020-01-01 
7 DDD  EEE  2013-01-01 2015-01-01 
8 DDD  EFG  2009-01-01 2012-01-01 

私はmatch1, match2を整合させるため、日付ときtableA'FAIL'statusを移入する必要があります - 開始と終了が - 互いに重なり合います。

ID = 2

場合、効果的な日付はID = 1と重なる、2008-01-01から2006-12-12あります。したがって、ID = 2'FAIL'になります。 ID = 6と同じです。

期待される結果:

id match1 match2 startdate enddate  Status 
1 AAA  BBB  2006-01-01 2007-01-01  NULL 
2 AAA  BBB  2006-12-12 2008-01-01  FAIL 
3 AAA  BBB  2008-01-01 2012-02-02  NULL 
4 AAA  BBB  2002-01-01 2004-01-01  NULL  
5 DDD  EEE  2009-01-01 2012-01-01  NULL 
6 DDD  EEE  2011-01-01 2020-01-01  FAIL 
7 DDD  EEE  2013-01-01 2015-01-01  NULL 
8 DDD  EFG  2009-01-01 2012-01-01  NULL (because It has different match2) 

また、私たちは、新しい着信がレコードを重なっ同じMATCH1及びMATCH2のための最初のレコードを維持し、失敗しています。

+0

実際に質問されていません... – Ben

+2

ID 7が失敗するのはなぜですか?それはID 6と重なる(交差する)。 –

+0

ベン - それは別の質問だった。さらに、私はそれに適切な解決策を得ていませんでした。 –

答えて

1

このためには、再帰的なCTEまたはカーソルが必要です。以下の再帰CTEアプローチ。

;WITH BaseData(id,match1,match2,startdate,enddate) 
    AS (SELECT 1,'AAA','BBB','2006-01-01','2007-01-01' UNION ALL 
     SELECT 2,'AAA','BBB','2006-12-12','2008-01-01' UNION ALL 
     SELECT 3,'AAA','BBB','2008-01-01','2012-02-02' UNION ALL 
     SELECT 4,'AAA','BBB','2002-01-01','2004-01-01' UNION ALL 
     SELECT 5,'DDD','EEE','2009-01-01','2012-01-01' UNION ALL 
     SELECT 6,'DDD','EEE','2011-01-01','2020-01-01' UNION ALL 
     SELECT 7,'DDD','EEE','2013-01-01','2015-01-01' UNION ALL 
     SELECT 8,'DDD','EFG','2009-01-01','2012-01-01' ), 
    RecursiveCTE 
    AS (SELECT id, 
       match1, 
       match2, 
       startdate, 
       enddate, 
       CAST(NULL AS VARCHAR(4)) AS Status, 
       enddate     AS LastSuccessfulEnd 
     FROM (SELECT *, 
         ROW_NUMBER() OVER (PARTITION BY match1, match2 
               ORDER BY startdate) RN 
       FROM BaseData) B 
     WHERE RN = 1 
     UNION ALL 
     SELECT id, 
       match1, 
       match2, 
       startdate, 
       enddate, 
       Status, 
       LastSuccessfulEnd 
     FROM (
       SELECT B.*, 
         rn = ROW_NUMBER() OVER (PARTITION BY B.match1, B.match2 
                ORDER BY B.startdate), 
         CASE 
         WHEN B.startdate < R.LastSuccessfulEnd THEN 'FAIL' 
         END AS Status, 
         CASE 
         WHEN B.startdate >= R.LastSuccessfulEnd THEN B.enddate 
         ELSE R.enddate 
         END AS LastSuccessfulEnd 
       FROM BaseData B 
         JOIN RecursiveCTE R 
          ON R.match1 = B.match1 
          AND R.match2 = B.match2 
          AND B.startdate > R.startdate) R 
     WHERE R.rn = 1) 
SELECT id, 
     match1, 
     match2, 
     startdate, 
     enddate, 
     Status 
FROM RecursiveCTE 
ORDER BY id 
2

ID 7が失敗するのはなぜですか?それはID 6と重複(交差)しますか? ID6が失敗したと

あなたはコメントで作られたこのポイントはSQLのみのソリューションの可能性を排除し、当社の考慮から除外されたためFAILのあなたの定義になるので

ID7は、失敗していません再帰的。つまり、何かが失敗したかどうかを知るためには、startendの日付を知るだけでは不十分です。前世代のレコードの合格または不合格のステータスも知っている必要があります。それはあなたのテーブルからのデータのために、これらの結果を返します

select a.*,(
    select top 1 b.id from tableA b 
    where a.match1=b.match1 and a.match2=b.match2 
    and a.startdate>b.startdate 
    and (case when a.startdate<b.startdate then b.startdate else a.startdate end) < 
    (case when a.enddate>b.enddate then b.enddate else a.enddate end) 
    order by b.startdate asc 
) as OverlappingId 
from tableA a 

ここ

は、あなたが最初の重複IDを判断するのに役立つことができ、クエリで、無視ルールを「失敗したレコードと重複することはカウントされません」

1 AAA BBB 2006-01-01 2007-01-01 NULL 
2 AAA BBB 2006-12-12 2008-01-01 1 
3 AAA BBB 2008-01-01 2012-02-02 NULL 
4 AAA BBB 2002-01-01 2004-01-01 NULL 
5 DDD EEE 2009-01-01 2012-01-01 NULL 
6 DDD EEE 2011-01-01 2020-01-01 5 
7 DDD EEE 2013-01-01 2015-01-01 6 
8 DDD EFG 2009-01-01 2012-01-01 NULL 

ルール「失敗したと重なっ」に注意を払う必要がある場合は、連続的にそれを適用する必要があります。 SQLはあまりよくありません。

関連する問題