Oracle
 sql >> база данни >  >> RDS >> Oracle

Как да хвана събитието „следващо“, когато отместването е променливо за елементи, които могат да се обработват многократно?

Това е проблем с пропуски и острови, но островите се дефинират от REQ транзакцията я правят малко по-сложна от някои.

Можете да използвате вложени водещи и изоставащи функции и някои манипулации, за да получите това, от което се нуждаете:

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;

С допълнителни записи за втори цикъл за елементи 1 и 2, които биха могли да дадат:

      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 показва всички междинни стъпки.

Не е толкова страшно, колкото може да изглежда на пръв поглед. Най-вътрешната заявка взема необработените данни и добавя допълнителна колона за водещи и закъснели транзакции. Вземайки само първия набор от записи на елемент-1, който ще бъде:

      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      

Забележете REQ-E появява се като последен lead_tran ? Това е първата transaction за втория цикъл на записи за този елемент и ще бъде полезен по-късно. Следващото ниво на заявка използва тези изпреварващи и изоставащи стойности и третира REQ стойности като начални и крайни маркери и използва тази информация, за да нулира всичко освен първия и последния запис за всеки цикъл.

      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     

Следващото ниво на заявка премахва всички редове, които не представляват началото или края (или и двете - вижте REQ-F във Fiddle), тъй като не се интересуваме от тях:

      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     

Вече имаме двойки редове за всеки цикъл (или един ред за REQ-F ). Последното ниво отново използва преднина и забавяне, за да запълни празните места; ако start_tran е null, тогава това е краен ред и трябва да използваме началните данни на предишния ред; ако end_tran е null, тогава това е начален ред и трябва да използваме крайните данни на следващия ред.

  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 

Това прави двата реда еднакви, така че distinct премахва дубликатите.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Свържете се от PHP към Oracle DB с помощта на Oracle Wallet

  2. ORA-12519 TNS:не е намерен подходящ манипулатор на услугата

  3. Как да стартирате различен sql, за да получите данни според предишните входни данни в pentaho kettle

  4. Сравняване с дата в Oracle sql

  5. Как да преброя броя на елементите във всички Oracle varrays от таблицата?