Redshift: поиск первых и последних событий в сеансе без идентификатора сеанса - PullRequest
0 голосов
/ 02 октября 2018

У меня есть таблица Redshift пользовательских событий в мобильном приложении:

|user|   screen   |collector_timestamp|
---------------------------------------
|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|

Сеанс - это действие, когда интервал между последовательными событиями меньше 1 часа.

Я хочунайдите сеанс (первый и последний collector_timestamp), в котором пользователь посещает 0 или более экранов, затем StartScreen, затем 0 или более экранов, затем OrderScreen, затем 0 или более экранов, затем FinishScreen.

Когда я пытаюсь применить тройное самостоятельное объединение, у меня возникает ошибка с permission denied to create temporary tables in database, потому что результат объединения не остается в памяти.

Как еще я могу найти подходящеесессий?

1 Ответ

0 голосов
/ 03 октября 2018

Сначала создайте идентификаторы сессии, используя оконную функцию 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 здесь .

...