sql >> Database teknologi >  >> RDS >> Oracle

opret id-kolonne baseret på aktivitetsdata

Jeg tror, ​​at dette vil gøre tricket:

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

Denne løsning er afhængig af den logiske kortslutning, der finder sted i CASE-udtrykket og det faktum, at event_type ikke er null. Det forudsætter også, at flere logouts i træk tælles som separate sessioner:

  1. Hvis den forrige række var en logout-række (og hvis der ikke er nogen tidligere række - dvs. for den første række i sættet - behandle den, som om der var en logout-række til stede), vil vi øge tælleren med én. (Log ud afslutter sessionen, så vi har altid en ny session efter et logout.)
  2. Hvis den aktuelle række er et logout, afslutter dette den eksisterende session. Derfor bør tælleren ikke øges.
  3. Hvis tiden for den aktuelle række er mere end en time fra den forrige række, skal du øge tælleren med én.
  4. Hvis den aktuelle række er en login-række, er det en ny session, så øg tælleren med én.
  5. I andre tilfælde øger vi ikke tælleren.

Når vi har gjort det, er det bare et spørgsmål om at lave en løbende total på tælleren.



  1. MySQL standardværdi som andet felts værdi

  2. Sådan fjerner du MySQL root-adgangskode

  3. fix mysql-forespørgsel for at returnere tilfældig række i undergruppen

  4. Hvordan kan jeg gemme multiple choice-værdier i en SQL-tabel? Hvordan skal bordet være?