合并两个MySQL查询时出现数据重复的问题求助
解决MySQL合并查询中的笛卡尔积重复问题
嘿,这个问题我太熟了——你遇到的是典型的笛卡尔积问题!原因很简单:你的两个子查询table1和table2直接用逗号放在FROM子句里,没有指定任何关联条件,MySQL会默认把第一个子查询的每一行和第二个子查询的所有行进行配对,33×33刚好就是1089行,这就是你看到大量重复数据的根源。
要实现按日期对应展示燃气消耗与采购数据的效果,你需要用JOIN语句,基于两个子查询的日期字段做关联。这里推荐用LEFT JOIN,这样能保留所有有消耗记录或采购记录的日期(如果某天只有消耗没有采购,采购列会显示NULL,反之亦然);如果只需要两边都有数据的日期,可以换成INNER JOIN。
修改后的查询代码如下:
SELECT table1.name, table1.reading_date, table1.`Gas Consumption (m3)`, table2.`Gas Purchase` FROM ( SELECT division.name, DATE(meter_data.reading_date) AS reading_date, SUM(meter_data.meter_delta) AS `Gas Consumption (m3)` FROM meter JOIN meter_data ON meter.meter_id = meter_data.meter_id JOIN division ON meter.division_id = division.division_id WHERE DATE(meter_data.reading_date) BETWEEN '2018-04-01' AND '2018-05-03' GROUP BY DATE(meter_data.reading_date), division.name -- 加上division.name符合分组规范,避免隐式逻辑错误 ) AS table1 LEFT JOIN ( SELECT DATE(receipt.receipt_date) AS receipt_date, SUM(CASE WHEN receipt_item.item_name = 'Gas' THEN receipt_item.item_amount ELSE 0 END) AS `Gas Purchase` FROM receipt JOIN receipt_item ON receipt.receipt_id = receipt_item.receipt_id WHERE DATE(receipt.receipt_date) BETWEEN '2018-04-01' AND '2018-05-03' GROUP BY DATE(receipt.receipt_date) ) AS table2 ON table1.reading_date = table2.receipt_date;
关键修改点说明:
- 把原查询中逗号连接子查询的方式改成
LEFT JOIN,并通过ON table1.reading_date = table2.receipt_date指定日期关联条件,彻底避免笛卡尔积 - 给两个子查询的日期字段分别起了别名
reading_date和receipt_date,让关联逻辑更清晰 - 原查询中
table1的GROUP BY只写了日期,建议加上division.name(符合MySQL的ONLY_FULL_GROUP_BY模式要求,避免潜在的分组逻辑错误) - 把原查询中的隐式连接(用WHERE条件关联表)改成显式的
JOIN语法,代码可读性更强
如果希望把所有日期(包括只有消耗或只有采购的)都完整展示,还可以先用UNION获取所有唯一日期,再分别LEFT JOIN两个子查询,不过上面的方案已经能满足大部分场景的需求啦。
内容的提问来源于stack exchange,提问作者Pronab Roy
相关产品推荐
相关产品推荐

