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

utwórz kolumnę id na podstawie danych o aktywności

Myślę, że to załatwi sprawę:

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

To rozwiązanie opiera się na obwodach logicznych, które mają miejsce w wyrażeniu CASE oraz na fakcie, że event_type nie jest null. Zakłada się również, że wielokrotne wylogowania z rzędu są liczone jako oddzielne sesje:

  1. Jeżeli poprzedni wiersz był wierszem wylogowania (i jeśli nie ma poprzedniego wiersza - tj. dla pierwszego wiersza w zestawie - potraktuj to tak, jakby był wiersz wylogowania), chcemy zwiększyć licznik o jeden. (Wylogowanie kończy sesję, więc zawsze mamy nową sesję po wylogowaniu.)
  2. Jeśli bieżący wiersz to wylogowanie, oznacza to zakończenie istniejącej sesji. Dlatego licznik nie powinien być zwiększany.
  3. Jeśli czas w bieżącym wierszu jest większy niż godzina od poprzedniego, zwiększ licznik o jeden.
  4. Jeśli bieżący wiersz jest wierszem logowania, to jest to nowa sesja, więc zwiększ licznik o jeden.
  5. W żadnym innym przypadku nie zwiększamy licznika.

Gdy już to zrobimy, wystarczy wykonać bieżące podsumowanie na ladzie.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. UID – Zwróć identyfikator bieżącej sesji w Oracle

  2. dlaczego 'create table' w skrypcie sql wykonuje się 3 razy, gdy używa się tylko 1 instrukcji create?

  3. Wybierz z tabeli, jeśli rekord został znaleziony w innej tabeli

  4. Jak zapisać dane Unicode w Oracle?

  5. Jak wyodrębnić ciąg znaków między nawiasami w zapytaniu Oracle sql