You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

MySQL中基于events表计算用户会话数及时长总和的SQL查询

计算用户会话数与总会话时长的MySQL查询方案

这是用户行为分析里很典型的会话统计需求,我会一步步带你实现对应的SQL逻辑:

核心思路

要统计会话,关键是给同一用户的连续事件划分会话组:当用户的两个相邻事件间隔超过2分钟(120秒)时,就认为前一个会话结束,新会话开始。之后我们只需要按用户和会话组来统计数量与时长即可。

完整SQL代码

WITH event_with_prev_time AS (
    -- 第一步:获取每个用户上一条事件的发生时间
    SELECT
        UserId,
        EventTime,
        LAG(EventTime) OVER (PARTITION BY UserId ORDER BY EventTime) AS prev_event_time
    FROM events
),
session_groups AS (
    -- 第二步:给每个事件分配会话ID,同一会话的ID相同
    SELECT
        UserId,
        EventTime,
        SUM(
            CASE 
                -- 首次事件或与上一事件间隔>2分钟时,标记为新会话起点
                WHEN prev_event_time IS NULL OR TIMESTAMPDIFF(SECOND, prev_event_time, EventTime) > 120 
                THEN 1 
                ELSE 0 
            END
        ) OVER (PARTITION BY UserId ORDER BY EventTime) AS session_id
    FROM event_with_prev_time
)
-- 第三步:按用户统计会话数和总时长
SELECT
    UserId,
    COUNT(DISTINCT session_id) AS session_count, -- 会话数量
    -- 将总秒数转换为时分秒格式(如'00:02:34')
    SEC_TO_TIME(SUM(TIMESTAMPDIFF(SECOND, MIN(EventTime), MAX(EventTime)))) AS total_session_duration
FROM session_groups
GROUP BY UserId;

代码逐段解释

  1. event_with_prev_time CTE
    使用LAG()窗口函数,按用户分组、事件时间排序,获取当前事件的上一条事件时间。这一步是为了计算相邻事件的时间间隔。

  2. session_groups CTE
    通过SUM() OVER()累计窗口函数来生成会话ID:

    • 如果是用户的第一条事件(prev_event_time IS NULL),直接标记为新会话(加1)
    • 如果当前事件和上一条事件的间隔超过120秒,也标记为新会话(加1)
    • 否则保持当前会话ID不变(加0)
      这样同一连续会话内的所有事件会拥有相同的session_id
  3. 最终统计

    • COUNT(DISTINCT session_id):统计每个用户的会话总数
    • SUM(TIMESTAMPDIFF(SECOND, MIN(EventTime), MAX(EventTime))):先计算每个会话的时长(会话最后一条事件时间减第一条),再求和得到总时长,最后用SEC_TO_TIME()转换为友好的时分秒格式。

特殊情况说明

  • 如果用户只有1条事件:会话数为1,会话时长为0(因为没有时间间隔),结果会显示为00:00:00,这符合逻辑。
  • 如果用户的事件间隔刚好等于2分钟:不会开启新会话,因为我们定义的是连续2分钟无事件才结束会话,等于2分钟的话属于连续活跃。

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

火山引擎 最新活动