You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用窗口函数实现会话分组标记及数据聚合(非T-SQL)

会话分组统计与窗口函数实现方案

给定原始数据集:

用户名事件时间是否新会话
userA2022-09-30 00:00:01.000000True
userA2022-09-30 00:00:02.000000False
userA2022-09-30 01:00:00.000000True
userA2022-09-30 02:00:00.000000True
userA2022-09-30 02:00:02.000000False
userA2022-09-30 02:00:04.000000False
userA2022-09-30 00:00:05.000000False
userB2022-09-30 03:00:00.000000True

需要先为每组连续记录(直到下一条是否新会话=True的记录)添加相同的分组标记值,再通过聚合得到如下会话统计结果(注:原示例中userA第一个会话的末次事件时间和事件数有误,已修正为按时间排序后的正确结果):

会话ID用户名首次事件时间末次事件时间事件数
1userA2022-09-30 00:00:01.0000002022-09-30 00:00:05.0000003
2userA2022-09-30 01:00:00.0000002022-09-30 01:00:00.0000001
3userA2022-09-30 02:00:00.0000002022-09-30 02:00:04.0000003
4userB2022-09-30 03:00:00.0000002022-09-30 03:00:00.0000001

以下是具体实现方案:

一、用窗口函数实现分组标记

核心逻辑是对是否新会话的起点做累计计数,从而为同一会话的记录分配相同的分组ID。

1. 使用SUM()窗口函数

将布尔值是否新会话转为数值(True=1,False=0),按用户名分区、事件时间排序后做累计求和:

SELECT 
    用户名,
    事件时间,
    是否新会话,
    SUM(CASE WHEN 是否新会话 THEN 1 ELSE 0 END) OVER (PARTITION BY 用户名 ORDER BY 事件时间) AS 会话分组ID
FROM 原始表
ORDER BY 用户名, 事件时间;

执行后,每个会话内的所有记录会被分配相同的会话分组ID,后续只需按用户名和会话分组ID聚合即可得到统计结果。

2. 使用COUNT()窗口函数

通过COUNT()仅统计是否新会话=True的记录,按用户名分区、事件时间排序累计计数,同样能生成会话分组ID:

SELECT 
    用户名,
    事件时间,
    是否新会话,
    COUNT(CASE WHEN 是否新会话 THEN 1 END) OVER (PARTITION BY 用户名 ORDER BY 事件时间) AS 会话分组ID
FROM 原始表
ORDER BY 用户名, 事件时间;

该方法与SUM()逻辑本质一致,都是对新会话起点做累计计数。

二、直接从原始数据生成最终统计结果的方案

可以将分组标记与聚合步骤合并,无需单独生成中间表:

SELECT 
    ROW_NUMBER() OVER (ORDER BY MIN(事件时间)) AS 会话ID,
    用户名,
    MIN(事件时间) AS 首次事件时间,
    MAX(事件时间) AS 末次事件时间,
    COUNT(*) AS 事件数
FROM (
    SELECT 
        *,
        SUM(CASE WHEN 是否新会话 THEN 1 ELSE 0 END) OVER (PARTITION BY 用户名 ORDER BY 事件时间) AS 会话分组ID
    FROM 原始表
) t
GROUP BY 用户名, 会话分组ID
ORDER BY 会话ID;

也可以用CTE(公共表表达式)优化可读性:

WITH 会话分组 AS (
    SELECT 
        用户名,
        事件时间,
        SUM(CASE WHEN 是否新会话 THEN 1 ELSE 0 END) OVER (PARTITION BY 用户名 ORDER BY 事件时间) AS 会话分组ID
    FROM 原始表
)
SELECT 
    ROW_NUMBER() OVER (ORDER BY MIN(事件时间)) AS 会话ID,
    用户名,
    MIN(事件时间) AS 首次事件时间,
    MAX(事件时间) AS 末次事件时间,
    COUNT(*) AS 事件数
FROM 会话分组
GROUP BY 用户名, 会话分组ID
ORDER BY 会话ID;

以上两种方式都能直接从原始表得到最终的会话统计结果,省去中间表处理步骤。

内容的提问来源于stack exchange,提问作者1131

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 20:30:48