sql >> データベース >  >> RDS >> Sqlserver

T-SQL の個別のメンバーごとに、複数の開始日と終了日の範囲で最初のギャップを特定する方法

    これを試してください:http://www.sqlfiddle.com/#!3/c3365/ 20

    with s as( select *, row_number() over(membercode による分割、開始日による順序) rn from tbl),gaps as(select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate ,datediff(d, a.enddate, b.startdate) as gapfrom s ajoin s b on b.membercode =a.membercode and b.rn =a.rn + 1)select membercode from gapsgroup by membercodehaving sum(gap <の場合) =1 なら 1 エンド) =count(*);  

    ここでクエリの進行状況を確認してください:http://www.sqlfiddle.com/#!3/ c3365/20

    仕組み、現在の終了日と次の開始日を比較し、日付のギャップを確認します:

     with s as( select *, row_number() over(partition by membercode order by startdate) rn from tbl)select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate ,datediff( d, a.enddate, b.startdate) as gapfrom s ajoin s b on b.membercode =a.membercode and b.rn =a.rn + 1;  

    出力:

    <プレ>|メンバーコード |開始日 |終了日 | NEXTSTARTDATE |ギャップ |------------------------------------------------ --------------| 1 | 2010-01-15 | 2010-01-20 | 2010-01-19 | -1 || 1 | 2010-01-19 | 2010-01-22 | 2010-01-20 | -2 || 1 | 2010-01-20 | 2010-01-25 | 2010-01-26 | 1 || 2 | 2010-01-20 | 2010-01-25 | 2010-01-30 | 5 || 2 | 2010-01-30 | 2010-02-05 | 2010-02-04 | -1 |

    次に、メンバーが同じ数の請求を行っており、請求の合計にギャップがないかどうかを確認します。

    with s as( select *, row_number() over(membercode による分割、開始日による順序) rn from tbl),gaps as(select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate ,datediff(d, a.enddate, b.startdate) as gapfrom s ajoin s b on b.membercode =a.membercode and b.rn =a.rn + 1)membercode を選択し、count(*) を count として、sum( case when gap <=1 then 1 end) as gapless_countfrom gapsgroup by membercode;  

    出力:

    <プレ>|メンバーコード |カウント | GAPLESS_COUNT |----------------------------------------------------| 1 | 3 | 3 || 2 | 2 | 1 |

    最後に、主張にギャップのないメンバーをフィルタリングします:

    with s as( select *, row_number() over(membercode による分割、開始日による順序) rn from tbl),gaps as(select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate ,datediff(d, a.enddate, b.startdate) as gapfrom s ajoin s b on b.membercode =a.membercode and b.rn =a.rn + 1)select membercode from gapsgroup by membercodehaving sum(gap <の場合) =1 なら 1 エンド) =count(*);  

    出力:

    <プレ>|メンバーコード |-------------| 1 |

    COUNT(*)> 1 を実行する必要がないことに注意してください 2 つ以上のクレームを持つメンバーを検出します。 LEFT JOIN を使用する代わりに 、 JOIN を使用します 、これにより、まだ 2 番目の要求を持っていないメンバーは自動的に破棄されます。 LEFT JOIN を使用することを選択した場合のバージョン (より長い) は次のとおりです。 代わりに (上記と同じ出力):

     with s as(select *, row_number() over(partition by membercode order by startdate) rnfrom tbl),gaps as(select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate ,datediff(d, a.enddate, b.startdate) as gapfrom s aleft join s b on b.membercode =a.membercode and b.rn =a.rn + 1)select membercode from gapsgroup by membercodehaving sum(case when gap <=1 その後 1 エンド) =カウント (ギャップ) およびカウント (*)> 1; -- 2 つ以上のクレームのみを持つメンバー  

    フィルタリング前に上記のクエリのデータを表示する方法は次のとおりです:

    with s as( select *, row_number() over(membercode による分割、開始日による順序) rn from tbl),gaps as(select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate ,datediff(d, a.enddate, b.startdate) as gapfrom s aleft join s b on b.membercode =a.membercode and b.rn =a.rn + 1)select * from gaps;  

    出力:

    <プレ>|メンバーコード |開始日 |終了日 | NEXTSTARTDATE |ギャップ |------------------------------------------------ ------------------| 1 | 2010-01-15 | 2010-01-20 | 2010-01-19 | -1 || 1 | 2010-01-19 | 2010-01-22 | 2010-01-20 | -2 || 1 | 2010-01-20 | 2010-01-25 | 2010-01-26 | 1 || 1 | 2010-01-26 | 2010-01-30 | (ヌル) | (ヌル) || 2 | 2010-01-20 | 2010-01-25 | 2010-01-30 | 5 || 2 | 2010-01-30 | 2010-02-05 | 2010-02-04 | -1 || 2 | 2010-02-04 | 2010-02-15 | (ヌル) | (ヌル) || 3 | 2010-02-15 | 2010-03-02 | (ヌル) | (ヌル) |

    編集 要件の明確化について:

    あなたの説明では、まだ 2 番目のクレームも持っていないメンバーを含めたいと考えていましたが、代わりにこれを行います:>http://sqlfiddle.com/#!3/c3365/22

     with s as(select *, row_number() over(partition by membercode order by startdate) rnfrom tbl),gaps as(select a.membercode, a.startdate, a.enddate, b.startdate as nextstartdate ,datediff(d, a.enddate, b.startdate) as gapfrom s aleft join s b on b.membercode =a.membercode and b.rn =a.rn + 1)select membercode from gapsgroup by membercodehaving sum(case when gap <=1 then 1 end) =count(gap)-- まだ 2 番目のクレームを持っていないメンバーも有効または count(nextstartdate) =0;   

    出力:

    <プレ>|メンバーコード |-------------| 1 || 3 |

    手法は、メンバーの nextstartdate をカウントすることです 、次の開始日がない場合 (つまり、count(nextstartdate) =0 ) その場合、それらは単一のクレームのみであり、有効でもあります。この OR を添付するだけです 状態:

    or count(nextstartdate) =0;   

    実際には、以下の条件でも十分ですが、クエリをより自己文書化したかったので、メンバーの nextstartdate に頼ることをお勧めします。 2 番目の要求をまだ持っていないメンバーをカウントするための別の条件は次のとおりです:

    or count(*) =1;  

    ところで、次の比較も変更する必要があります:

    sum(case when gap <=1 then 1 end) =count(*)  

    これに (LEFT JOIN を使用しているため) 今):

    sum(case when gap <=1 then 1 end) =count(gap)  

    1. OracleでのBLOBストレージの長さ

    2. MySQLトリガーのクイックアップデート

    3. AirflowをOracleデータベースに接続する方法

    4. 1つの列に複数の行値がある複数の行を1つにマージします