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.