2014-11-12 3 views
1

Я хотел бы GROUP BY несколько строк в SQL на основе «времени бездействия», , что означает заметные большие промежутки между отметками времени, чтобы распознать пользователя сеансов.найти сеансы пользователей, группируя близлежащие временные метки

Пусть эта таблица действия в SQLite базы данных:

_actions_ 
| id | userID | timestamp | actionType | 

Теперь я могу просмотреть все действия пользователя и его тип сгруппированных по часу, месяц, год и т.д.

SELECT 
    userID, strftime('%H', timestamp), group_concat(actionType) 
FROM 
    actions 
GROUP BY userID, strftime('%H', timestamp); 

Однако, это не совсем то, что я хочу. Рассмотрим это:

| 1 | 333 | 13.11.2014-20:59 | action6 | 
| 2 | 333 | 13.11.2014-21:01 | action3 | 
| 3 | 333 | 13.11.2014-21:47 | action5 | 

Мой пример сливается в строке 1 и строке 2 + 3, однако, если мы предположим, сеанс таймаут 30 минут мы должны получить ряд 1 + 2 и строка 3. Есть SQL-идеи?

Конечно, можно загрузить базу данных и в R, Pandas и т. Д. И проверить для каждого пользователя, если current_timestamp - last_timestamp> 30min, но действительно ли это путь?

ответ

0

Чтобы вычислить, где строка является первой строкой в ​​сеансе, проверьте, существует ли какая-либо другая строка в течение предыдущих 30 минут:

SELECT *, 
     NOT EXISTS (SELECT 1 
        FROM actions AS prev 
        WHERE userid = actions.userid 
        AND timestamp < actions.timestamp 
        AND timestamp >= datetime(actions.timestamp, '-30 minutes') 
       ) AS first 
FROM actions; 

id   userid  timestamp   actiontype first  
---------- ---------- ---------------- ---------- ---------- 
1   333   2014-11-13 20:59 action6  1   
2   333   2014-11-13 21:01 action3  0   
3   333   2014-11-13 21:47 action5  1   

Но его не помогает непосредственно с группировкой; нам нужно какое-то значение, уникальное для всех строк в группе.

Возьмем идентификатор первой строки в группе. Чтобы найти эту первую строку группы текущей строки, мы берем последней строки, которая является первой строкой некоторые группы, и это не после текущей строки:

SELECT *, 
     (SELECT id 
     FROM actions AS first 
     WHERE userid = actions.userid 
      AND timestamp <= actions.timestamp 
      AND NOT EXISTS (SELECT 1 
          FROM actions AS prev 
          WHERE userid = first.userid 
          AND timestamp < first.timestamp 
          AND timestamp >= datetime(first.timestamp, '-30 minutes') 
         ) 
     ORDER BY timestamp DESC 
     LIMIT 1 
     ) AS sessionid 
FROM actions; 

id   userid  timestamp   actiontype sessionid 
---------- ---------- ---------------- ---------- ---------- 
1   333   2014-11-13 20:59 action6  1   
2   333   2014-11-13 21:01 action3  1   
3   333   2014-11-13 21:47 action5  3   

Для сделайте этот запрос эффективным, столбец timestamp должен быть проиндексирован.

Смежные вопросы