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

编写SQL查询为用户生成会话编号(连续记录间隔≤30分钟为同一会话)

生成用户会话编号的SQL解决方案

刚好最近处理过类似的会话分组需求,这个问题其实用窗口函数就能轻松搞定,我给你拆解下思路和具体实现代码:

核心思路

要实现按30分钟间隔划分会话,关键是判断每条记录和上一条的时间差:

  • 按User_id分组,先把每个用户的记录按时间戳排序
  • 用窗口函数拿到上一条记录的时间,计算两者的间隔
  • 只要间隔超过30分钟,就标记为新会话的起点,最后通过累计这些标记来生成会话编号

适配主流数据库的SQL代码

WITH user_sorted AS (
    SELECT 
        User_id,
        impression_ts,
        -- 计算当前记录与上一条的时间差(分钟),不同数据库语法可能略有差异
        TIMESTAMPDIFF(MINUTE, 
                      LAG(impression_ts) OVER (PARTITION BY User_id ORDER BY impression_ts),
                      impression_ts) AS mins_since_last
    FROM your_table
),
session_flags AS (
    SELECT 
        User_id,
        impression_ts,
        -- 第一条记录或者间隔超30分钟,标记为新会话
        CASE 
            WHEN mins_since_last IS NULL OR mins_since_last > 30 THEN 1 
            ELSE 0 
        END AS is_new_session
    FROM user_sorted
)
SELECT 
    User_id,
    impression_ts,
    -- 累计求和得到会话编号
    SUM(is_new_session) OVER (PARTITION BY User_id ORDER BY impression_ts) AS session
FROM session_flags
ORDER BY User_id, impression_ts;

代码细节解释

  1. user_sorted CTE:先给每个用户的记录按时间排序,用LAG()窗口函数获取当前记录的上一条时间,计算两者的分钟差。第一条记录没有上一条,所以mins_since_last会是NULL。
  2. session_flags CTE:给新会话的起点打标记——第一条记录肯定是新会话,或者当前记录和上一条间隔超过30分钟,也标记为1,其他情况标记为0。
  3. 最终查询:对每个用户的标记进行累计求和,每遇到一个1(新会话起点),求和结果就加1,这样就生成了连续的会话编号。

验证你的数据

把你的输入数据代入这个查询,会得到和预期完全一致的结果:

| User_id | impression_ts | session |
+---------+---------------+---------+
| 101 | 10:30 AM | 1 |
| 101 | 10:45 AM | 1 |
| 101 | 10:50 AM | 1 |
| 101 | 11:30 AM | 2 |
| 101 | 12:30 PM | 3 |

如果你的数据库时间函数语法不同(比如PostgreSQL用EXTRACT(EPOCH FROM (impression_ts - LAG(impression_ts) OVER (...)))/60来算分钟差),只要调整时间差的计算部分就行,核心逻辑是通用的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 12:02:48