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

MySQL兼容5+/8+ 统计每日及对应日期前30天注册用户数

需求背景

现有users用户表,核心字段如下:

  • user_id:用户唯一标识
  • created_at:时间戳类型,存储用户注册时间
    需要实现两类统计:
  1. 按自然日统计当日新增注册用户数
  2. 对每个统计日期,同步计算该日期往前30天(含统计当日)的累计注册用户总数
    要求最终SQL同时兼容MySQL 5.x、MySQL 8.x版本。
已实现的单场景SQL

每日注册用户数统计

SELECT DATE_FORMAT(date(created_at),'%d %M %Y') AS Days, COUNT(user_id) as Profiles
FROM users
GROUP BY YEAR(created_at), MONTH(created_at), DAY(created_at);

固定当前日期的近30天注册数统计

SELECT current_date(),COUNT(user_id) 
FROM users 
WHERE created_at >=  NOW() - INTERVAL 30 DAY;

现有问题:上述第二个SQL固定以当前时间为基准计算30天累计值,需要将固定日期替换为第一个SQL生成的所有业务日期,逐日期计算对应时间窗口的累计注册量。

跨版本兼容实现方案

不依赖MySQL 8.0才支持的窗口函数,采用子查询预聚合+表关联的写法,可直接在MySQL 5.5+所有版本运行:

SELECT 
    DATE_FORMAT(daily.reg_date, '%d %M %Y') AS Days,
    daily.daily_cnt AS Profiles,
    COUNT(u.user_id) AS last_30days_total
FROM (
    -- 预聚合得到所有有注册记录的日期、当日注册量
    SELECT DATE(created_at) AS reg_date, COUNT(user_id) AS daily_cnt
    FROM users
    GROUP BY DATE(created_at)
) daily
-- 关联用户表按时间窗口统计累计值
LEFT JOIN users u 
    ON u.created_at >= daily.reg_date - INTERVAL 30 DAY
    AND u.created_at < daily.reg_date + INTERVAL 1 DAY
GROUP BY daily.reg_date, daily.daily_cnt
ORDER BY daily.reg_date;
实现说明
  • 兼容性:未使用窗口函数、CTE等MySQL 8.0新增特性,所有语法均兼容MySQL 5.x全版本
  • 性能优化:时间区间判断未对created_at字段使用函数转换,可直接命中created_at字段上的索引,避免全表扫描
  • 逻辑对齐:时间窗口范围与原单场景SQL完全一致,覆盖统计日期前30天0点至统计日期当日24点的所有注册记录,包含统计当日数据
  • 逻辑简化:内层聚合使用DATE(created_at)分组,与原SQL中按年、月、日分别分组的效果完全一致,写法更简洁

如果需要返回无注册记录的空日期,需要先生成连续自然日的日历表再关联统计,当前实现与原每日统计SQL逻辑对齐,仅返回存在注册行为的日期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 06:24:16