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

créer une colonne d'identification basée sur les données d'activité

Je pense que cela fera l'affaire :

WITH EVENTS AS (SELECT 'abc' usr, to_date('2016-01-01 08:00:00', 'yyyy-mm-dd hh24:mi:ss') event_ts, 'login' event_type FROM dual UNION ALL
                SELECT 'abc' usr, to_date('2016-01-01 08:25:00', 'yyyy-mm-dd hh24:mi:ss') event_ts, 'Stuff' event_type FROM dual UNION ALL
                SELECT 'abc' usr, to_date('2016-01-01 10:00:00', 'yyyy-mm-dd hh24:mi:ss') event_ts, 'Stuff' event_type FROM dual UNION ALL
                SELECT 'abc' usr, to_date('2016-01-01 14:00:00', 'yyyy-mm-dd hh24:mi:ss') event_ts, 'login' event_type FROM dual UNION ALL
                SELECT 'xyz' usr, to_date('2015-12-31 18:00:00', 'yyyy-mm-dd hh24:mi:ss') event_ts, 'login' event_type FROM dual UNION ALL
                SELECT 'xyz' usr, to_date('2016-01-01 08:00:00', 'yyyy-mm-dd hh24:mi:ss') event_ts, 'Logout' event_type FROM dual UNION ALL
                SELECT 'def' usr, to_date('2016-01-01 08:00:00', 'yyyy-mm-dd hh24:mi:ss') event_ts, 'Logout' event_type FROM dual UNION ALL
                SELECT 'def' usr, to_date('2016-01-01 08:15:00', 'yyyy-mm-dd hh24:mi:ss') event_ts, 'Logout' event_type FROM dual)
SELECT usr,
       event_ts,
       event_type,
       SUM(counter) OVER (PARTITION BY usr ORDER BY event_ts) session_id
FROM   (SELECT usr,
               event_ts,
               event_type,
               CASE WHEN LAG(event_type, 1, 'Logout') OVER (PARTITION BY usr ORDER BY event_ts) = 'Logout' THEN 1
                    WHEN event_type = 'Logout' THEN 0
                    WHEN event_ts - LAG(event_ts) OVER (PARTITION BY usr ORDER BY event_ts) > 1/24 THEN 1
                    WHEN event_type = 'login' THEN 1
                    ELSE 0
               END counter
        FROM   EVENTS);

USR EVENT_TS            EVENT_TYPE SESSION_ID
--- ------------------- ---------- ----------
abc 2016-01-01 08:00:00 login               1
abc 2016-01-01 08:25:00 Stuff               1
abc 2016-01-01 10:00:00 Stuff               2
abc 2016-01-01 14:00:00 login               3
def 2016-01-01 08:00:00 Logout              1
def 2016-01-01 08:15:00 Logout              2
xyz 2015-12-31 18:00:00 login               1
xyz 2016-01-01 08:00:00 Logout              1

Cette solution repose sur le court-circuit logique qui se produit dans l'expression CASE et sur le fait que event_type n'est pas nul. Il suppose également que plusieurs déconnexions consécutives sont comptées comme des sessions distinctes :

  1. Si la ligne précédente était une ligne de déconnexion (et s'il n'y a pas de ligne précédente - c'est-à-dire pour la première ligne de l'ensemble - traitez-la comme si une ligne de déconnexion était présente), nous voulons augmenter le compteur de un. (Les déconnexions mettent fin à la session, nous avons donc toujours une nouvelle session après une déconnexion.)
  2. Si la ligne actuelle est une déconnexion, cela met fin à la session existante. Par conséquent, le compteur ne doit pas être augmenté.
  3. Si l'heure de la ligne actuelle est supérieure à une heure de la ligne précédente, augmentez le compteur d'une unité.
  4. Si la ligne actuelle est une ligne de connexion, il s'agit d'une nouvelle session, augmentez donc le compteur de un.
  5. Pour tout autre cas, nous n'augmentons pas le compteur.

Une fois que nous avons fait cela, il suffit de faire un total cumulé sur le compteur.