2017-07-17 2 views
0

私はこのようなテーブル行を持っています。最後に状態が変化したときのレコードとグループの期間を見つける

acc start_dat end_dat n_type 
aa 1/1/2017 2/2/2017 er 
aa 2/2/2017 4/2/2017 er 
aa 4/2/2017 1/3/2017 ok 
aa 1/3/2017 12/3/2017 ok 
aa 12/3/2017 15/4/2017 er 
aa 15/4/2017 3/5/2017 er 
aa 3/5/2017 5/5/2017 er 
aa 5/5/2017  null  ok 
bb 12/2/2017 4/3/2017 er 
bb 4/3/2017 20/3/2017 er 
bb 20/3/2017 13/4/2017 er 
bb 13/4/2017 4/5/2017 ok 
bb 4/5/2017 7/6/2017 er 
bb 7/6/2017 3/7/2017 er 
bb 3/7/2017  null  ok 

私は

acc start_dat end_dat duration_day 
aa 12/3/2017 5/5/2017 52 
bb 4/5/2017 3/7/2017 60 

を終了するグループに開始時に計算日のためend_Dat = nullを指定し、[OK]に変更前の最後のステータスをしたいあなたはそれを解決するための任意のアイデアを持っていますか?

+0

'n_type'、** er **、** ok **の2つの値がありますか? 3つ以上の可能な値があり、最後のステータス変更が必要な場合(例えば、** er **から** st **(別の 'n_type'と仮定して)、最新の** ok * *あなたが受け入れた答えは、** st **ステータスの開始日と終了日を見つけられません - 同じものと同じように扱われる** er **と** st **が見つかります – mathguy

答えて

0

あなたの数学が間違っているようだ、2017年12月3日からの日数2017年は54歳で、52歳ではありませんでした。

同じn_typeの連続する行をグループ化する必要があります。 「連続」はstart_datの順であり、グループ化はaccごとに別々に行われます。このような「ギャップと島」の問題でグループ識別子を作成するためのTabibitosanメソッドの直接的な応用です。 「Tabibitosanメソッド」は、partition by句を異なる2つのrow_number()関数の違いを、以下のソリューションの最も内側のサブクエリで使用することです。

それ以外のクエリは標準です。グループacc, n_type, grpgrpは、最も内側のサブクエリで作成された新しいグループ化フラグ)で、各グループの最小開始日と最大終了日を計算し、n_type = 'ok'のすべてのグループを無視した後に最高のgrpフラグを持つグループを選択します。

select acc, start_dat, end_dat, end_dat - start_dat as duration_day 
from (
     select acc, min(start_dat) as start_dat, max(end_dat) as end_dat, 
        row_number() over (partition by acc order by grp desc) as rn 
     from  (
        select acc, start_dat, end_dat, n_type, 
         row_number() over (partition by acc   order by start_dat) - 
         row_number() over (partition by acc, n_type order by start_dat) 
         as grp 
        from inputs 
       ) 
     where n_type != 'ok' 
     group by acc, n_type, grp 
     ) 
where rn = 1 
; 
+0

http:// rextester。 com/JNF33335このロジックは素晴らしかった!!私は理解するために多くの時間を費やす。ありがとうございます。 –

+0

これがどのように動作するかを理解するには、最も内側のサブクエリを単独で実行します(前後のすべてを削除します)。 Googleは "Tabibitosanの方法"のための数多くの議論と例を見つける。その部分を理解した後、中間サブクエリ(サブサブクエリとともに)のみを実行し、それが何をするかを見てください。次に、完全なクエリを実行することができます。各ステップが達成することと次のステップでどのように使用されるかを参照してください。 – mathguy

0

あなたは、各レコードの後に​​「OK」のレコードの数をカウントして、集約のためにすることを使用することができます:/ 5月5日に

select acc, min(start_dat), max(end_dat), 
     (max(end_dat) - min(start_dat)) as diff 
from (select t.*, 
      sum(case when n_type = 'ok' then 1 else 0 end) over (partition by acc order by start_dat desc) as numoks_after 
     from t 
    ) t 
where numoks_after = 1 and n_type <> 'ok' 
group by acc; 
+0

http: //rextester.com/DGJIWX21590和訳を使用していません。このロジックはすばらしいです。ありがとうございます。 –

+0

あなたはどちらの回答も受け入れることができますが、この回答を受け入れない理由はありますか? –

+0

http: //rextester.com/CXB24635最後に+1のレコードが同じ優先順位であれば、この問題を解決することはできません。numoks_afterの合計は正しくありませんが、このロジックにはお答えいただきありがとうございます。 –

関連する問題