Как сделать запрос SQL для подсчета сеансов, состоящих из нескольких действий - PullRequest
0 голосов
/ 24 января 2020

Я новичок в SQL, и я не понимаю, как сделать один запрос. У меня есть таблица, которая состоит из трех столбцов: user_id, timestamp, event_code. И это выглядит так:

    user_id     timestamp                 event_code
    ------------------------------------------------
0   0001e90f    2019-09-06T17:53:46.937Z    2000
1   0001e90f    2019-09-06T17:54:17.519Z    2000
2   0001e90f    2019-09-06T17:54:56.302Z    2000
3   0001e90f    2019-09-06T17:54:56.387Z    3010
4   0001e90f    2019-09-06T17:55:03.253Z    3110
5   0001e90f    2019-09-06T17:55:06.279Z    4070
6   0001e90f    2019-09-06T17:55:06.913Z    4070
7   0001e90f    2019-09-06T17:55:07.546Z    4070
8   0001e90f    2019-09-06T17:55:07.979Z    4070
9   0001e90f    2019-09-06T17:55:08.566Z    4070

Мне нужно посчитать количество сеансов в течение дня. Сеанс представляет собой последовательность из трех событий (2020 -> 3020 -> 4020). Между этими тремя событиями могут быть разные события, но разница времени между 4020 и 2020 не может превышать 1 час.

В результате я ожидаю, что такая таблица

    user_id     start_session       end_session
    ----------------------------------------------------
0   0001e90f    2019-09-06T17:53:46 2019-09-06T18:50:46
1   0002e90f    2019-09-06T17:59:46 2019-09-06T18:37:46
2   0003e90f    2019-09-06T16:23:46 2019-09-06T17:00:00
3   0004e90f    2019-09-06T17:09:46 2019-09-06T17:58:27
4   0001e90f    2019-09-07T12:33:46 2019-09-07T12:55:20
5   0002e90f    2019-09-07T17:53:46 2019-09-06T18:50:46

Как я понимаю, мне нужно выбрать метку времени события 2020 года и метку времени 4020 единицы и подсчитать дельту для каждого пользователя. Затем мне нужно сгруппировать их по часам и посчитать количество таких users_id (их дельты). Но я не понимаю, как написать такое условие, и как я могу указать, что между ними должно быть событие 3020.

Буду благодарен за любую помощь.

Ответы [ 2 ]

0 голосов
/ 24 января 2020

Вы можете использовать оконные функции, чтобы получить «будущую» информацию, а затем простую логику c, чтобы определить сеансы.

Это сработает, если у вас есть некоторая дисциплина в ваших данных. Если данные не контролируются - например, несколько 2020-х подряд - тогда я бы предложил вам задать новый вопрос с более подробным объяснением.

Итак, сеансы:

select t.*
from (select t.*,
             min(case when event_code = 3020 then timestamp end) over (partition by user_id order by timestamp desc) as next_3020,
             min(case when event_code = 4020 then timestamp end) over (partition by user_id order by timestamp desc) as next_4020
      from t
     ) t
where event_code = 2020 and
      next_3020 > timestamp and
      next_4020 > next_3020 and
      next_4020 < timestamp + interval '1 hour';

Количество в день тогда:

select timestamp::date, count(*)
from (select t.*,
             min(case when event_code = 3020 then timestamp end) over (partition by user_id order by timestamp desc) as next_3020,
             min(case when event_code = 4020 then timestamp end) over (partition by user_id order by timestamp desc) as next_4020
      from t
     ) t
where event_code = 2020 and
      next_3020 > timestamp and
      next_4020 > next_3020 and
      next_4020 < timestamp + interval '1 hour'
group by timestamp::date;
0 голосов
/ 24 января 2020

Попробуйте это. Это не совсем правильный сценарий, но, возможно, он даст идею

SELECT 
s1.userid, 
s1.event_code,
s2.event_code,
s1.timestamp,
s2.timestamp
FROM test AS s1
INNER JOIN test AS s2 ON s1.userid = s2.userid
WHERE 
s1.event_code = '2020' AND 
s2.event_code = '4020' AND 
TIMEDIFF(DATE_FORMAT(s2.timestamp,'%H:%i:%s'), DATE_FORMAT(s1.timestamp, '%H:%i:%s')) >= 0 AND TIMEDIFF(DATE_FORMAT(s2.timestamp,'%H:%i:%s'), DATE_FORMAT(s1.timestamp, '%H:%i:%s')) <= MAKETIME(1, 0, 0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...