我在移动应用中有一个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
出现错误,因为联接的结果未在内存中触发。
我还能如何找到合适的会话?
答案 0 :(得分:1)
首先使用Redshift中的LAG
窗口函数创建会话ID。
然后,仅使用您关心的屏幕在会话中聚合顺序事件。使用此功能,您可以筛选出所需的确切模式。该示例在一个查询中执行此操作,但实际上可能应使用多个表来完成,因此您可以引用每个会话的详细数据。以下代码使用您提供的数据在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 here上有一个示例。