Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Bagaimana cara mengambil acara "berikutnya" ketika offset adalah variabel untuk item yang dapat diproses berulang kali?

Ini adalah masalah celah dan pulau, tetapi pulau-pulau tersebut didefinisikan oleh REQ transaksi membuatnya sedikit lebih rumit daripada beberapa.

Anda dapat menggunakan fungsi lead dan lag bersarang dan beberapa manipulasi untuk mendapatkan apa yang Anda butuhkan:

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;

Dengan catatan tambahan untuk siklus kedua untuk item 1 dan 2 yang dapat memberikan:

      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 Fiddle menunjukkan semua langkah perantara.

Ini tidak begitu menakutkan seperti yang terlihat pada pandangan pertama. Kueri terdalam mengambil data mentah dan menambahkan kolom tambahan untuk transaksi prospek dan jeda. Mengambil hanya set pertama dari catatan item-1 yang akan menjadi:

      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      

Pemberitahuan REQ-E muncul sebagai lead_tran terakhir ? Itu transaction pertama untuk catatan siklus kedua untuk item ini, dan akan berguna nanti. Tingkat kueri berikutnya menggunakan nilai lead dan lag tersebut dan memperlakukan REQ nilai sebagai penanda awal dan akhir, dan menggunakan informasi itu untuk menghapus semuanya kecuali catatan pertama dan terakhir untuk setiap siklus.

      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     

Tingkat kueri berikutnya menghapus setiap baris yang tidak mewakili awal atau akhir (atau keduanya - lihat REQ-F di Fiddle) karena kami tidak tertarik dengan mereka:

      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     

Kami sekarang memiliki pasangan baris untuk setiap siklus (atau satu baris untuk REQ-F ). Level terakhir menggunakan lead dan lag lagi untuk mengisi kekosongan; jika start_tran is null maka ini adalah baris akhir dan kita harus menggunakan data awal baris sebelumnya; jika end_tran adalah null maka ini adalah baris awal dan kita harus menggunakan data akhir baris berikutnya.

  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 

Itu membuat kedua baris sama, jadi distinct menghapus duplikat.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle + masalah penyandian Java saat memasukkan

  2. cara mengekstrak format tanggal dari oracle string

  3. Oracle ExecuteScalar dalam pemrograman paralel terkadang mengembalikan null

  4. Cara mendapatkan usia dalam tahun, bulan, dan hari menggunakan Oracle

  5. Perbandingan tanggal Oracle di mana klausa