sql >> Database teknologi >  >> RDS >> Oracle

Hvordan får jeg fat i den "næste" hændelse, når forskydningen er variabel for elementer, der kan behandles gentagne gange?

Dette er et hul-og-ø-problem, men øerne er defineret af en REQ transaktion gør det lidt mere kompliceret end nogle andre.

Du kan bruge indlejrede lead- og lag-funktioner og noget manipulation for at få det, du har brug for:

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 yderligere registreringer for en anden cyklus for punkt 1 og 2, der kunne give:

      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 violin viser alle de mellemliggende trin.

Det er ikke helt så skræmmende, som det kan se ud ved første øjekast. Den inderste forespørgsel tager de rå data og tilføjer en ekstra kolonne for lead- og lagtransaktioner. Tager kun det første sæt af post-1 poster, der ville være:

      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      

Bemærk REQ-E dukker op som den sidste lead_tran ? Det er den første transaction for den anden cyklus af poster for denne vare, og vil være nyttig senere. Det næste niveau af forespørgsel bruger disse lead- og lag-værdier og behandler REQ værdier som start- og slutmarkører og bruger denne information til at nulstille alt undtagen den første og sidste post for hver cyklus.

      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     

Det næste niveau af forespørgsel fjerner alle rækker, der ikke repræsenterer starten eller slutningen (eller begge dele - se REQ-F i Violinen), da vi ikke er interesserede i 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 af rækker for hver cyklus (eller en enkelt række for REQ-F ). Det sidste niveau bruger bly og lag igen til at udfylde de tomme felter; hvis start_tran er null, så er dette en slutrække, og vi bør bruge den forrige rækkes startdata; hvis end_tran er null, så er dette en startrække, og vi skal bruge den næste rækkes 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 begge rækker ens, så den distinct fjerner dubletterne.



  1. Rediger mysql-tabel

  2. Ekskluder linjeresultater, der har NULL-værdi i et hvilket som helst felt?

  3. Sådan får du row_number i MySQL

  4. Mangler hukommelse (tildelt 50855936) (forsøgte at tildele 50331646 bytes)