Detta är ett problem med luckor och öar, men öarna definieras av en REQ
transaktion gör det lite mer komplicerat än vissa.
Du kan använda kapslade lead- och lagfunktioner och viss manipulation för att få det du behöver:
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;
Med ytterligare poster för en andra cykel för objekt 1 och 2 som skulle kunna ge:
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 visar alla mellanstegen.
Det är inte riktigt så skrämmande som det kan se ut vid första anblicken. Den innersta frågan tar rådata och lägger till en extra kolumn för lead- och eftersläpningstransaktioner. Tar bara den första uppsättningen post-1-poster som skulle vara:
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
Observera REQ-E
dyker upp som den sista lead_tran
? Det är den första transaction
för den andra omgången av poster för detta objekt, och kommer att vara användbar senare. Nästa nivå av frågan använder dessa lead- och fördröjningsvärden och behandlar REQ
värden som start- och slutmarkörer och använder den informationen för att nollställa allt utom den första och sista posten för varje cykel.
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
Nästa nivå av frågan tar bort alla rader som inte representerar början eller slutet (eller båda - se REQ-F
i fiolen) eftersom vi inte är intresserade av dem:
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
Vi har nu par av rader för varje cykel (eller en enda rad för REQ-F
). Den sista nivån använder bly och lag igen för att fylla i tomrummen; om start_tran
är null så är detta en slutrad och vi bör använda föregående rads startdata; om end_tran
är null så är detta en startrad och vi bör använda nästa rads slutdata.
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
Det gör båda raderna lika, så distinct
tar bort dubbletterna.