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

如何查询用户首会话至当前月的各月会话数(含零值)

问题:统计指定用户从首次会话到当前月的各月会话数(含0计数)

需要获取指定用户从首次会话月份到当前月份的各月会话数量,无会话的月份需显示0计数。现有session表包含session_id、user_id、start_time字段,但执行以下SQL后仅返回10个月份,无法覆盖到当前月,需修复:

SELECT DATE_FORMAT(DATE_ADD(min_month, INTERVAL m.n MONTH), '%Y-%m') as month,
       COALESCE(COUNT(c.consumption), 0) as total_consumption
FROM
  (SELECT DATE_FORMAT(MIN(start_time), '%Y-%m-01') as min_month
   FROM session
   WHERE user_id = 'sGcO42wMx1ZHXwZpZH3KWwWXzd13') as start_month
CROSS JOIN
  (SELECT n
   FROM (SELECT 0 n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
         UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) as n) as m
LEFT JOIN session as c ON DATE_FORMAT(c.start_time, '%Y-%m') = DATE_FORMAT(DATE_ADD(start_month.min_month, INTERVAL m.n MONTH), '%Y-%m')
   AND c.user_id = 'sGcO42wMx1ZHXwZpZH3KWwWXzd13'
GROUP BY month
ORDER BY month ASC;

解决方案

原SQL的问题在于手动生成的数字序列仅包含0-9,最多只能生成10个月份。如果用户首次会话到当前月的间隔超过9个月,就会漏掉后续月份。以下是两种修复方案:

方案1:使用递归CTE(适用于MySQL 8.0+、PostgreSQL等支持递归的数据库)

递归CTE会自动生成从首次会话月到当前月的所有月份,无需手动指定数量:

WITH RECURSIVE month_series AS (
    -- 起始:用户首次会话的月份
    SELECT DATE_FORMAT(MIN(start_time), '%Y-%m-01') AS month_date
    FROM session
    WHERE user_id = 'sGcO42wMx1ZHXwZpZH3KWwWXzd13'
    
    UNION ALL
    
    -- 递归生成下一个月,直到当前月
    SELECT DATE_ADD(month_date, INTERVAL 1 MONTH)
    FROM month_series
    WHERE month_date < DATE_FORMAT(NOW(), '%Y-%m-01')
)
SELECT 
    DATE_FORMAT(ms.month_date, '%Y-%m') AS month,
    COALESCE(COUNT(s.session_id), 0) AS total_sessions
FROM month_series ms
LEFT JOIN session s 
    ON DATE_FORMAT(s.start_time, '%Y-%m') = DATE_FORMAT(ms.month_date, '%Y-%m')
    AND s.user_id = 'sGcO42wMx1ZHXwZpZH3KWwWXzd13'
GROUP BY ms.month_date
ORDER BY ms.month_date ASC;

方案2:生成足够多的数字序列(兼容老版本MySQL)

通过交叉连接生成0-99的数字序列,覆盖100个月,再过滤掉超过当前月的部分:

SELECT 
    DATE_FORMAT(DATE_ADD(min_month, INTERVAL m.n MONTH), '%Y-%m') AS month,
    COALESCE(COUNT(s.session_id), 0) AS total_sessions
FROM
    (SELECT DATE_FORMAT(MIN(start_time), '%Y-%m-01') AS min_month
     FROM session
     WHERE user_id = 'sGcO42wMx1ZHXwZpZH3KWwWXzd13') AS start_month
CROSS JOIN
    -- 生成0-99的数字,覆盖100个月
    (SELECT a.n + b.n * 10 AS n
     FROM (SELECT 0 n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
           UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
     CROSS JOIN (SELECT 0 n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
                 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b) AS m
LEFT JOIN session s 
    ON DATE_FORMAT(s.start_time, '%Y-%m') = DATE_FORMAT(DATE_ADD(start_month.min_month, INTERVAL m.n MONTH), '%Y-%m')
    AND s.user_id = 'sGcO42wMx1ZHXwZpZH3KWwWXzd13'
-- 过滤掉超过当前月的无效月份
WHERE DATE_ADD(start_month.min_month, INTERVAL m.n MONTH) <= DATE_FORMAT(NOW(), '%Y-%m-01')
GROUP BY month
ORDER BY month ASC;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 13:33:26