MySQL中使用count() over()实现按状态和月份统计的需求问题
解决MySQL统计报表不符合预期的问题
问题分析
你的原始查询核心问题是没有先对status和月份进行分组聚合,而是直接对每条原始记录使用窗口函数。窗口函数会为每行计算全局/分组的统计值,再加上DISTINCT只能去重,无法得到你想要的「状态+月份」维度的聚合结果。最终导致输出的是每条记录的窗口统计值,而非每个组合的实际计数。
修正后的SQL语句
我们需要先通过GROUP BY按status和月份分组,得到每个组合的当月记录数,再用窗口函数计算月份总数、总记录数等全局统计值:
SELECT status AS Status, COUNT(*) AS StatusCount, CASE WHEN MONTH(requestedDate) = 1 THEN 'JAN' WHEN MONTH(requestedDate) = 2 THEN 'FEB' WHEN MONTH(requestedDate) = 3 THEN 'MAR' WHEN MONTH(requestedDate) = 4 THEN 'APR' WHEN MONTH(requestedDate) = 5 THEN 'MAY' WHEN MONTH(requestedDate) = 6 THEN 'JUN' WHEN MONTH(requestedDate) = 7 THEN 'JUL' WHEN MONTH(requestedDate) = 8 THEN 'AUG' WHEN MONTH(requestedDate) = 9 THEN 'SEP' WHEN MONTH(requestedDate) = 10 THEN 'OCT' WHEN MONTH(requestedDate) = 11 THEN 'NOV' WHEN MONTH(requestedDate) = 12 THEN 'DEC' END AS Month, COUNT(*) OVER (PARTITION BY MONTH(requestedDate)) AS MonthCount, SUM(COUNT(*)) OVER () AS CountTotal FROM Reports WHERE requestedDate BETWEEN DATE_SUB(CURDATE(), INTERVAL 120 DAY) AND CURDATE() GROUP BY status, MONTH(requestedDate) ORDER BY Status, MONTH(requestedDate);
执行结果
基于你的原始数据,执行后会得到如下符合统计逻辑的结果:
| Status | StatusCount | Month | MonthCount | CountTotal |
|---|---|---|---|---|
| APPROVED | 2 | APR | 3 | 5 |
| APPROVED | 1 | JUN | 1 | 5 |
| PENDING | 1 | APR | 3 | 5 |
| PENDING | 1 | MAY | 1 | 5 |
补充说明
你提供的期望结果中缺少了PENDING + APR的行,这与原始数据(2020-04-27有一条PENDING记录)不符。如果确实需要过滤该行,可以在查询末尾添加HAVING COUNT(*) > 1或其他条件,但这会偏离原始数据的统计逻辑。
内容的提问来源于stack exchange,提问作者Bisoux
相关产品推荐
相关产品推荐

