SQL:单个 OVER 子句可以支持多个窗口函数吗?

con*_*lee 7 sql window-functions apache-spark-sql

假设我有一个综合浏览事件列表,每个事件都有一个会话 ID。对于每个事件,我想添加该事件会话中按时间顺序排列的第一个综合浏览量的时间和 URL。例如,假设我的事件在表中test,如下所示:

uid | session_id | timestamp | url
----------------------------------------------------
u1    0            0           a.com/
u1    1            1           a.com/p1
u1    1            2           a.com/p2
Run Code Online (Sandbox Code Playgroud)

我想要一个产生以下结果的 SQL 命令:

uid | session_id | timestamp | url      | s_timestamp | s_url
---------------------------------------------------------------------
u1    0            0           a.com/     0             a.com/
u1    1            1           a.com/p1   1             a.com/p1
u1    1            2           a.com/p2   1             a.com/p1
Run Code Online (Sandbox Code Playgroud)

窗口函数似乎是这里的方法,但我对它们还很陌生。以下语句生成所需的表,但我想知道它是否不是最优的

SELECT
    uid,
    session_id,
    timestamp,
    url,
    first_value(url) OVER (PARTITION BY uid, session_id ORDER BY timestamp ASC) s_url,
    first_value(timestamp) OVER (PARTITION BY uid, session_id ORDER BY timestamp ASC) s_timestamp
FROM test
Run Code Online (Sandbox Code Playgroud)

特别是,我使用该子句两次似乎是错误的OVER。有没有办法使用单个 OVER 子句从会话中选择按时间顺序排列的第一个 URL 和时间戳?我正在使用 SPARK SQL,但我会接受任何适用于多个主要 SQL 系统的答案。

con*_*lee 7

可以使用WINDOW关键字来命名一个窗口,然后可以在 SELECT 子句中引用该窗口:

SELECT
    uid,
    session_id,
    timestamp,
    url,
    first_value(url) OVER w s_url,
    first_value(timestamp) OVER w s_timestamp
FROM test
WINDOW w AS (PARTITION BY uid, session_id ORDER BY timestamp ASC)
Run Code Online (Sandbox Code Playgroud)

这适用于 Apache Spark SQL 和 HiveQL。