Redshift:在没有任何会话ID的情况下查找会话中的第一个和最后一个事件

Posted

技术标签:

【中文标题】Redshift:在没有任何会话ID的情况下查找会话中的第一个和最后一个事件【英文标题】:Redshift: Finding first and last events in session without any session id 【发布时间】:2018-10-02 12:38:30 【问题描述】:

我有一个移动应用中用户事件的 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 出现错误,因为联接的结果不会在内存中存储。

我还能如何找到合适的课程?

【问题讨论】:

你的问题似乎比你的标题更广泛,所以我对你的问题感到困惑。 @GordonLinoff 我改写了标题 除了 StartScreen、FinishScreen 和 OrderScreen 之外,“screen”还有其他可能的值吗?我认为您需要提供更大的示例数据集来说明问题。 @Nathan 是的,还有其他屏幕。 【参考方案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 上有一个示例。

【讨论】:

以上是关于Redshift:在没有任何会话ID的情况下查找会话中的第一个和最后一个事件的主要内容,如果未能解决你的问题,请参考以下文章

查询缓存amazon redshift

在不使用 aws 凭据的情况下连接 Redshift 和 Python(在 emr 上运行)

已发布的应用程序显示“无法在没有验证证明、会话信息、临时证明或注册 ID 的情况下创建 PhoneAuthCredential。”

Redshift 在多个条件下加入,但仅在一个条件不匹配时返回

调试会话在没有暂停的情况下完成

如何在没有连接的情况下为 postgres (Redshift) 生成 SQL 查询?