Сначала создайте идентификаторы сессии, используя оконную функцию LAG
в Redshift.Затем объедините упорядоченные события в течение сеанса, используя только те экраны, которые вам нужны.Используя это, вы можете фильтровать по точному шаблону, который вы ищете.Пример делает это в одном запросе, но, вероятно, на практике это должно быть сделано с использованием нескольких таблиц, чтобы вы могли ссылаться на подробные данные для каждого сеанса.Следующий код создает автономный пример в Redshift, используя предоставленные вами данные, с некоторыми дополнительными записями для демонстрации результатов.
DROP TABLE IF EXISTS events;
CREATE TABLE events
("user" INT
, "screen" VARCHAR(12)
, "collector_timestamp" TIMESTAMP
);
INSERT INTO events
("user", "screen", "collector_timestamp")
VALUES
(1111, 'StartScreen', '2018-10-01 07:02:33'),
(1111, 'FinishScreen', '2018-10-01 07:02:34'),
(1112, 'OrderScreen', '2018-10-01 07:10:33'),
(1113, 'StartScreen', '2018-10-01 09:01:27'),
(1112, 'StartScreen', '2018-10-01 09:10:33'),
(1112, 'OrderScreen', '2018-10-01 09:11:33'),
(1112, 'FinishScreen', '2018-10-01 09:12:33')
;
WITH sessionized_events AS(
SELECT *
, "user"||'_'|| SUM(new_session) OVER (PARTITION BY USER ORDER BY collector_timestamp ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS session_id
FROM(
SELECT
*
, CASE
WHEN EXTRACT(EPOCH FROM collector_timestamp)
- LAG(EXTRACT(EPOCH FROM collector_timestamp))
OVER (PARTITION BY "user" ORDER BY collector_timestamp) >= 60 * 60
THEN 1
ELSE 0
END AS new_session
FROM events
) s
)
SELECT
session_id
FROM sessionized_events
GROUP BY 1
HAVING listagg(DISTINCT screen)
WITHIN GROUP (ORDER BY collector_timestamp) like ('%StartScreen%OrderScreen%FinishScreen')
;
Результаты:
session_id
----------
1112_1
Postgres имеет другой синтаксис, чемRedshift, но для тех, у кого нет кластера Redshift для запуска, у меня есть пример SQLFiddle здесь .