Google Charts堆叠数据系列的MySQL多条件查询问题
解决MySQL单查询统计双系列堆叠柱状图数据的问题
核心方案是使用条件聚合替代WHERE多状态过滤,在同一个查询中分别计算Sales和Quotes两个系列的月度数值,避免数据叠加问题,同时适配Google Charts的堆叠柱状图数据源格式。
完整查询示例
假设你的项目表名为projects,包含字段start_date、end_date、sell_value、probability、status,以下查询会生成带月度维度的双系列数据:
WITH RECURSIVE date_range AS ( -- 生成覆盖所有项目起止日期的月度列表 SELECT DATE_FORMAT(MIN(start_date), '%Y-%m-01') AS month_date FROM projects UNION ALL SELECT DATE_ADD(month_date, INTERVAL 1 MONTH) FROM date_range WHERE month_date <= (SELECT DATE_FORMAT(MAX(end_date), '%Y-%m-01') FROM projects) ) SELECT DATE_FORMAT(dr.month_date, '%Y-%m') AS month, -- 计算Sales系列:仅统计Work Order状态的项目,拆分sell_value到对应月度 SUM( CASE WHEN p.status = 'Work Order' THEN p.sell_value / TIMESTAMPDIFF(MONTH, p.start_date, p.end_date) ELSE 0 END ) AS sales, -- 计算Quotes系列:仅统计Quote状态的项目,sell_value乘概率后拆分到对应月度 SUM( CASE WHEN p.status = 'Quote' THEN (p.sell_value * p.probability) / TIMESTAMPDIFF(MONTH, p.start_date, p.end_date) ELSE 0 END ) AS quotes FROM date_range dr LEFT JOIN projects p -- 关联条件:确保项目时间范围覆盖当前统计月份 ON dr.month_date BETWEEN DATE_FORMAT(p.start_date, '%Y-%m-01') AND DATE_FORMAT(p.end_date, '%Y-%m-01') GROUP BY dr.month_date ORDER BY dr.month_date;
关键逻辑说明
- 日期维度生成:用递归CTE
date_range生成所有需要统计的月度,确保每个月份都有数据行,即使该月无Sales/Quotes数据(对应值为0)。 - 条件聚合:通过
CASE WHEN在SUM函数中做状态判断,只对符合条件的项目计算数值,不同状态的计算逻辑完全分离,不会出现数据叠加。 - 月度数值拆分:使用
TIMESTAMPDIFF(MONTH, start_date, end_date)计算项目的总持续月数,将数值平均拆分到每个覆盖的月份,比简单按天数折算更贴合月度统计需求。
注意事项
- 如果
probability存储的是百分比整数(比如50代表50%),需要调整为(p.sell_value * p.probability / 100)。 - 如果项目仅持续不足1个月,
TIMESTAMPDIFF会返回0,此时可以添加判断避免除以0,比如IF(TIMESTAMPDIFF(MONTH, p.start_date, p.end_date) = 0, 1, TIMESTAMPDIFF(MONTH, p.start_date, p.end_date))。
内容的提问来源于stack exchange,提问作者TomC
相关产品推荐
相关产品推荐

