Oracle
 sql >> Base de données >  >> RDS >> Oracle

Comment puis-je saisir l'événement "suivant" lorsque le décalage est variable pour les éléments qui peuvent être traités de manière répétée ?

C'est un problème de lacunes et d'îlots, mais les îlots étant définis par un REQ transaction le rendent un peu plus compliqué que certains.

Vous pouvez utiliser des fonctions d'avance et de retard imbriquées et quelques manipulations pour obtenir ce dont vous avez besoin :

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;

Avec des enregistrements supplémentaires pour un second cycle pour les items 1 et 2 qui pourraient donner :

      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 montrant toutes les étapes intermédiaires.

Ce n'est pas aussi effrayant que cela puisse paraître à première vue. La requête la plus interne prend les données brutes et ajoute une colonne supplémentaire pour les transactions en avance et en retard. En prenant uniquement le premier ensemble d'enregistrements de l'élément 1, ce serait :

      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      

Remarque REQ-E apparaissant comme le dernier lead_tran ? C'est la première transaction pour le deuxième cycle d'enregistrements pour cet article, et sera utile plus tard. Le niveau de requête suivant utilise ces valeurs d'avance et de retard et traite REQ valeurs comme marqueurs de début et de fin, et utilise ces informations pour tout annuler sauf le premier et le dernier enregistrement de chaque cycle.

      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     

Le niveau suivant de la requête supprime toutes les lignes qui ne représentent pas le début ou la fin (ou les deux - voir REQ-F dans le Fiddle) car ils ne nous intéressent pas :

      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     

Nous avons maintenant des paires de lignes pour chaque cycle (ou une seule ligne pour REQ-F ). Le dernier niveau utilise à nouveau l'avance et le décalage pour remplir les blancs; si le start_tran est nul, il s'agit d'une ligne de fin et nous devons utiliser les données de début de la ligne précédente ; si end_tran est nul, il s'agit d'une ligne de début et nous devons utiliser les données de fin de la ligne suivante.

  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 

Cela rend les deux lignes identiques, donc le distinct supprime les doublons.