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

SQL查询需求:筛选按顺序执行动作1、2、3且间隔小于1小时的用户会话

解决用户按顺序执行1→2→3且间隔小于1小时的SQL查询方案

别发愁啦!这个需求其实就是要追踪用户动作的顺序和时间间隔,咱们一步步来搞定它。首先我得先假设你的数据表结构(如果和实际有出入,你可以对应调整字段名):假设表名为user_actions,包含字段user_id(用户ID)、action_id(动作编号,比如1、2、3)、action_time(动作执行的时间戳)。

方法一:支持中间有其他动作的通用方案

如果你的需求是「用户执行了1,之后执行了2(间隔<1小时),之后又执行了3(和2间隔<1小时)」,不管中间有没有其他动作,那用自连接+窗口函数的方案最稳妥:

WITH ranked_actions AS (
    SELECT
        user_id,
        action_id,
        action_time,
        -- 给每个用户的动作按时间排序,生成序号
        ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY action_time) AS action_rank
    FROM user_actions
)
-- 关联三次动作记录,匹配1→2→3的顺序和时间要求
SELECT DISTINCT
    r1.user_id
FROM ranked_actions r1
JOIN ranked_actions r2 
    ON r1.user_id = r2.user_id 
    AND r2.action_rank > r1.action_rank  -- 确保动作2在动作1之后
    AND r2.action_id = 2
    -- 动作2和动作1的间隔小于1小时(MySQL写法,其他数据库可调整)
    AND TIMESTAMPDIFF(HOUR, r1.action_time, r2.action_time) < 1
JOIN ranked_actions r3 
    ON r2.user_id = r3.user_id 
    AND r3.action_rank > r2.action_rank  -- 确保动作3在动作2之后
    AND r3.action_id = 3
    -- 动作3和动作2的间隔小于1小时
    AND TIMESTAMPDIFF(HOUR, r2.action_time, r3.action_time) < 1
WHERE r1.action_id = 1;

代码解释:

  • ranked_actions这个CTE(公共表表达式)给每个用户的动作按时间排了序号,保证我们能严格按顺序关联动作。
  • 三次自连接分别匹配动作1、2、3,通过action_rank确保顺序,通过TIMESTAMPDIFF检查时间间隔。
  • DISTINCT用来避免同一个用户因为有多个符合条件的动作序列被重复返回。

方法二:仅适用于1→2→3连续执行的高效方案

如果你的需求是用户必须连续执行1、2、3(中间没有其他动作),那用LEAD窗口函数会更简洁高效:

WITH action_sequence AS (
    SELECT
        user_id,
        action_id,
        action_time,
        -- 获取当前动作的下一个动作ID和时间
        LEAD(action_id, 1) OVER (PARTITION BY user_id ORDER BY action_time) AS next_action,
        LEAD(action_time, 1) OVER (PARTITION BY user_id ORDER BY action_time) AS next_action_time,
        -- 获取当前动作的下下个动作ID和时间
        LEAD(action_id, 2) OVER (PARTITION BY user_id ORDER BY action_time) AS second_next_action,
        LEAD(action_time, 2) OVER (PARTITION BY user_id ORDER BY action_time) AS second_next_action_time
    FROM user_actions
)
SELECT DISTINCT user_id
FROM action_sequence
WHERE 
    action_id = 1
    AND next_action = 2
    AND second_next_action = 3
    AND TIMESTAMPDIFF(HOUR, action_time, next_action_time) < 1
    AND TIMESTAMPDIFF(HOUR, next_action_time, second_next_action_time) < 1;

代码解释:

  • LEAD函数可以直接获取当前行之后第N行的数据,这里我们一次性拿到当前动作的下一个和下下个动作信息。
  • 直接筛选出当前动作是1,下一个是2,下下个是3,且相邻间隔都小于1小时的用户。

注意事项

  • 不同数据库的时间差函数写法不同:比如PostgreSQL用EXTRACT(HOUR FROM r2.action_time - r1.action_time) < 1,SQL Server用DATEDIFF(HOUR, ...),你要根据自己用的数据库调整。
  • 确保action_time是时间类型(比如TIMESTAMP、DATETIME),否则无法正确计算时间差。
  • 如果需要返回具体的会话详情(比如会话的开始/结束时间),可以修改SELECT语句,比如加上r1.action_time AS session_start, r3.action_time AS session_end。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:13:28