Oracle
 sql >> база данни >  >> RDS >> Oracle

създаване на колона за идентификатор въз основа на данни за дейността

Мисля, че това ще свърши работа:

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

Това решение разчита на логическото късо съединение, което се случва в израза CASE и на факта, че event_type не е null. Освен това се предполага, че няколко последователни излизания се броят като отделни сесии:

  1. Ако предишният ред е бил ред за излизане (и ако няма предишен ред - т.е. за първия ред в набора - третирайте го така, сякаш има ред за излизане), искаме да увеличим брояча с единица. (Излизането прекратява сесията, така че винаги имаме нова сесия след излизане.)
  2. Ако текущият ред е излизане, това прекратява съществуващата сесия. Следователно броячът не трябва да се увеличава.
  3. Ако времето на текущия ред е по-голямо от един час от предишния ред, увеличете брояча с едно.
  4. Ако текущият ред е ред за влизане, това е нова сесия, така че увеличете брояча с единица.
  5. За всеки друг случай ние не увеличаваме брояча.

След като направим това, остава само да направим текуща обща сума на брояча.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Условие на задействане във всички редове

  2. Символът амперсанд (&) се игнорира в Oracle ORDER BY

  3. Заявка за намиране на служители, които са взели повече от отговарящия на условията отпуск по отношение на техните длъжности

  4. Кога данните във временната таблица на сесията на Oracle ще бъдат изтрити?

  5. Как да получите известие от базата данни до C++ приложение