MySQL统计DAU/WAU/MAU时窗口函数语法错误排查与解决
问题解决与修正后的SQL语句
语法错误直接原因
MySQL的窗口框架语法中,preceding 前的数值不需要加负号,你写的 -6 preceding 是错误语法,应该改为 6 preceding,同理 -29 preceding 改为 29 preceding。除此之外还有几处语法细节问题:
- CTE(公用表表达式)需要用
WITH关键字开头(MySQL 8.0+支持) - 表名
temp table应该是temp_table(下划线连接,不能有空格) - 查询字段
casted date应为casted_date(下划线连接)
逻辑错误修正
你的原语句用 sum(dau) 计算WAU/MAU是错误的,因为同一个用户可能在多日活跃,直接累加会重复统计,WAU是过去7天内去重的活跃用户数,MAU同理。需要先保留每日的活跃用户明细,再通过窗口函数统计去重用户数。
最终修正后的SQL
假设你的 temp_table 中 date 字段需要转换为日期格式(对应你写的 casted_date),且指定起始日期为 '2024-01-01',可以用以下语句:
WITH daily_active_users AS ( -- 先获取每日去重的活跃用户,过滤指定起始日期之后的数据 SELECT DATE(date) AS casted_date, user_id FROM temp_table WHERE DATE(date) >= '2024-01-01' -- 指定起始日期 GROUP BY casted_date, user_id ), dau_stats AS ( -- 计算DAU SELECT casted_date, COUNT(user_id) AS dau FROM daily_active_users GROUP BY casted_date ) SELECT casted_date, dau, -- 计算过去7天(含当日)的去重活跃用户数(WAU) COUNT(DISTINCT user_id) OVER ( ORDER BY casted_date RANGE BETWEEN INTERVAL 6 DAY PRECEDING AND CURRENT ROW ) AS wau, -- 计算过去30天(含当日)的去重活跃用户数(MAU) COUNT(DISTINCT user_id) OVER ( ORDER BY casted_date RANGE BETWEEN INTERVAL 29 DAY PRECEDING AND CURRENT ROW ) AS mau FROM daily_active_users GROUP BY casted_date, dau ORDER BY casted_date;
关键说明
- 使用
RANGE BETWEEN INTERVAL n DAY PRECEDING替代ROWS,因为如果存在日期断层(比如某天没有活跃用户),ROWS会取前6行数据而非前6天,RANGE基于日期范围更准确。 - 先通过
daily_active_users表保留每日去重的用户,再统计DAU和窗口内的去重用户数,避免重复统计。 - 明确添加了指定起始日期的过滤条件,符合你“不能使用current_date对比”的要求。
内容的提问来源于stack exchange,提问作者Prabuddha Dasgupta
相关产品推荐
相关产品推荐

