sql >> Databasteknik >  >> RDS >> Oracle

skapa id-kolumn baserat på aktivitetsdata

Jag tror att det här kommer att göra susen:

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

Denna lösning förlitar sig på den logiska kortslutningen som sker i CASE-uttrycket och det faktum att event_type inte är null. Det förutsätter också att flera utloggningar i rad räknas som separata sessioner:

  1. Om den föregående raden var en utloggningsrad (och om det inte finns någon föregående rad - dvs. för den första raden i uppsättningen - behandla den som om en utloggningsrad fanns), vill vi öka räknaren med en. (Utloggningar avslutar sessionen, så vi har alltid en ny session efter en utloggning.)
  2. Om den aktuella raden är en utloggning, avslutar detta den befintliga sessionen. Därför bör räknaren inte ökas.
  3. Om tiden för den aktuella raden är längre än en timme från föregående rad, öka räknaren med en.
  4. Om den aktuella raden är en inloggningsrad är det en ny session, så öka räknaren med en.
  5. I andra fall ökar vi inte räknaren.

När vi har gjort det är det bara att göra en löpande summa på disken.



  1. Hibernate:själv gå med förvirring?

  2. Räkna där kolumnen ändras till specifikt värde i postgres

  3. Exponera SQL Server-databasobjekt som filer i ett filsystem

  4. SQL Data Manipulation Language