sql >> Databasteknik >  >> RDS >> Oracle

Hur tar jag tag i "nästa"-händelsen när offset är variabel för objekt som kan bearbetas upprepade gånger?

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.



  1. Åtkomst nekad för användaren 'root'@'localhost' (med lösenord:JA) - Inga privilegier?

  2. Lista alla främmande nycklar på en tabell i SQL Server

  3. Inga resultat efter att ha tagit bort mysql ft_stopword_file

  4. Matchningsalgoritm i SQL