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

繰り返し処理できるアイテムのオフセットが可変である場合、「次の」イベントを取得するにはどうすればよいですか?

    これはギャップと島の問題ですが、島はREQによって定義されています トランザクションにより、一部よりも少し複雑になります。

    ネストされたリード関数とラグ関数、およびいくつかの操作を使用して、必要なものを取得できます。

    select distinct item,
      coalesce(start_tran,
        lag(start_tran) over (partition by item order by timestamp)) as start_tran,
      coalesce(end_tran,
        lead(end_tran) over (partition by item order by timestamp)) as end_tran,
      coalesce(end_time, 
        lead(end_time) over (partition by item order by timestamp))
        - coalesce(start_time,
            lag(start_time) over (partition by item order by timestamp)) as time
    from (
      select item, timestamp, start_tran, start_time, end_tran, end_time
      from (
        select item,
          timestamp,
          case when lag_tran is null or transaction like 'REQ%'
            then transaction end as start_tran,
          case when lag_tran is null or transaction like 'REQ%'
            then timestamp end as start_time,
          case when lead_tran is null or lead_tran like 'REQ%'
            then transaction end as end_tran,
          case when lead_tran is null or lead_tran like 'REQ%'
            then timestamp end as end_time
        from (
          select item, transaction, timestamp,
            lag(transaction)
              over (partition by item order by timestamp) as lag_tran,
            lead(transaction)
              over (partition by item order by timestamp) as lead_tran
          from transactions
        )
      )
      where start_tran is not null or end_tran is not null
    )
    order by item, start_tran;
    

    アイテム1と2の2番目のサイクルの追加レコードで次のようになります。

          ITEM START_TRAN END_TRAN   TIME      
    ---------- ---------- ---------- -----------
             1 REQ-A      PICKUP     0 1:53:30.0 
             1 REQ-E      PICKUP     0 1:23:30.0 
             2 REQ-B      MAIL       0 0:24:13.0 
             2 REQ-F      REQ-F      0 0:0:0.0   
             3 REQ-C      PICKUP     0 1:46:30.0 
             4 REQ-D      PULL       0 0:23:59.0 
             5 REQ-A      PICKUP     0 1:43:59.0 
    

    SQLフィドル すべての中間ステップを示しています。

    一見したほど怖くはありません。最も内側のクエリは生データを取得し、リードトランザクションとラグトランザクション用の列を追加します。アイテム1レコードの最初のセットだけを取得すると、次のようになります。

          ITEM TRANSACTION TIMESTAMP                LAG_TRAN   LEAD_TRAN
    ---------- ----------- ------------------------ ---------- ----------
             1 REQ-A       2014-07-31T09:51:32Z                PULL       
             1 PULL        2014-07-31T10:22:21Z     REQ-A      TRANSFER   
             1 TRANSFER    2014-07-31T10:22:23Z     PULL       ARRIVE     
             1 ARRIVE      2014-07-31T11:45:01Z     TRANSFER   PICKUP     
             1 PICKUP      2014-07-31T11:45:02Z     ARRIVE     REQ-E      
    

    REQ-Eに注意してください 最後のlead_tranとしてポップアップします ?これが最初のtransactionです このアイテムのレコードの2番目のサイクルで、後で役立ちます。次のレベルのクエリは、これらの先行値と遅延値を使用して、REQを処理します。 値を開始マーカーと終了マーカーとして使用し、その情報を使用して、各サイクルの最初と最後のレコードを除くすべてを無効にします。

          ITEM TIMESTAMP                START_TRAN START_TIME               END_TRAN   END_TIME               
    ---------- ------------------------ ---------- ------------------------ ---------- ------------------------
             1 2014-07-31T09:51:32Z     REQ-A      2014-07-31T09:51:32Z                                         
             1 2014-07-31T10:22:21Z                                                                             
             1 2014-07-31T10:22:23Z                                                                             
             1 2014-07-31T11:45:01Z                                                                             
             1 2014-07-31T11:45:02Z                                         PICKUP     2014-07-31T11:45:02Z     
    

    次のレベルのクエリは、開始または終了(またはその両方)を表していない行を削除します。REQ-Fを参照してください。 フィドルで)私たちはそれらに興味がないので:

          ITEM TIMESTAMP                START_TRAN START_TIME               END_TRAN   END_TIME               
    ---------- ------------------------ ---------- ------------------------ ---------- ------------------------
             1 2014-07-31T09:51:32Z     REQ-A      2014-07-31T09:51:32Z                                         
             1 2014-07-31T11:45:02Z                                         PICKUP     2014-07-31T11:45:02Z     
    

    これで、各サイクルの行のペア(またはREQ-Fの単一の行)ができました。 )。最終レベルでは、リードとラグを再度使用して空白を埋めます。 start_tranの場合 nullの場合、これは終了行であり、前の行の開始データを使用する必要があります。 end_tranの場合 nullの場合、これは開始行であり、次の行の終了データを使用する必要があります。

      ITEM START_TRAN START_TIME               END_TRAN   END_TIME                 TIME      
    
         1 REQ-A      2014-07-31T09:51:32Z     PICKUP     2014-07-31T11:45:02Z     0 1:53:30.0 
         1 REQ-A      2014-07-31T09:51:32Z     PICKUP     2014-07-31T11:45:02Z     0 1:53:30.0 
    

    これにより、両方の行が同じになるため、distinct 重複を削除します。



    1. 範囲外の数値:mysqlの1264

    2. WordPressブログをCodeIgniterビューにリンクする

    3. MySQLとPHPを使用したJQueryポーリング。どのように?

    4. Windowsコマンドスクリプトでsql*plusを使用してフローを制御するにはどうすればよいですか?