Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Jak przechwycić zdarzenie „następne”, gdy przesunięcie jest zmienne dla elementów, które można wielokrotnie przetwarzać?

Jest to problem z lukami i wyspami, ale wyspy są definiowane przez REQ transakcja sprawia, że ​​jest to nieco bardziej skomplikowane niż niektóre.

Możesz użyć zagnieżdżonych funkcji lead i lag oraz pewnych manipulacji, aby uzyskać to, czego potrzebujesz:

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;

Z dodatkowymi zapisami dla drugiego cyklu dla pozycji 1 i 2, które mogą dać:

      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 

Skrzypce SQL pokazuje wszystkie etapy pośrednie.

To nie jest tak przerażające, jak mogłoby się wydawać na pierwszy rzut oka. Najbardziej wewnętrzne zapytanie pobiera nieprzetworzone dane i dodaje dodatkową kolumnę dla transakcji potencjalnej i opóźnionej. Biorąc tylko pierwszy zestaw rekordów pozycji 1, który byłby:

      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      

Zwróć uwagę REQ-E pojawia się jako ostatni lead_tran ? To pierwsza transaction dla drugiego cyklu ewidencji dla tej pozycji i przyda się później. Następny poziom zapytania wykorzystuje te wartości lead i lag i traktuje REQ wartości jako znaczniki początku i końca, i wykorzystuje te informacje do unieważnienia wszystkiego oprócz pierwszego i ostatniego rekordu w każdym cyklu.

      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     

Następny poziom zapytania usuwa wszystkie wiersze, które nie reprezentują początku ani końca (lub obu - patrz REQ-F na skrzypcach), ponieważ nie jesteśmy nimi zainteresowani:

      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     

Mamy teraz pary wierszy dla każdego cyklu (lub pojedynczy wiersz dla REQ-F ). Końcowy poziom ponownie wykorzystuje lead i lag, aby wypełnić puste miejsca; jeśli start_tran ma wartość null, to jest wiersz końcowy i powinniśmy użyć danych początkowych poprzedniego wiersza; jeśli end_tran ma wartość null, to jest wiersz początkowy i powinniśmy użyć danych końcowych następnego wiersza.

  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 

To sprawia, że ​​oba wiersze są takie same, więc distinct usuwa duplikaty.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle Developer Tools dla błędów Visual Studio .net

  2. Jak najlepiej zarządzać historycznymi wartościami wyszukiwania w bazie danych?

  3. Różnica między wyrocznią DATE a TIMESTAMP

  4. Oracle:ORA-12154:Problem z TNS:64-bitowy Excel/Windows 10 64-bitowy

  5. ORA-00054:zasób zajęty i pozyskiwanie z określonym NOWAIT lub upłynął limit czasu