关联三张MySQL表未获预期结果,寻求技术解决方案
解决MySQL三张表关联出现非预期结果的问题
我明白你现在遇到的问题啦——直接用LEFT JOIN关联account、bread_sale和water_sale的时候,会因为同一个账户在两个销售表中有多条记录,产生笛卡尔积,导致数据重复或者不符合预期的结果。咱们先理清楚你的数据,再给出针对性的解决方案。
你的表数据
account表
| ac | name |
|---|---|
| 120 | Tom |
| 130 | Jony |
| 140 | Jone |
bread_sale表
| ac | pcs | amount | date |
|---|---|---|---|
| 120 | 12 | 60 | 2018-01-03 |
| 120 | 10 | 50 | 2018-01-04 |
| 140 | 8 | 40 | 2018-01-04 |
| 130 | 5 | 25 | 2018-01-05 |
water_sale表
| ac | pcs | amount | date |
|---|---|---|---|
| 130 | 2 | 30 | 2018-01-03 |
| 130 | 5 | 75 | 2018-01-04 |
| 140 | 3 | 45 | 2018-01-04 |
| 130 | 4 | 60 | 2018-01-05 |
| 120 | 5 | 75 | 2018-01-07 |
问题根源
你之前的查询(应该是类似SELECT ... FROM account LEFT JOIN bread_sale ON account.ac = bread_sale.ac LEFT JOIN water_sale ON account.ac = water_sale.ac)会触发笛卡尔积:比如Jony(ac=130)在bread_sale有1条记录,在water_sale有3条记录,关联后会生成3条重复的面包销售数据,每条对应一条水销售数据,这显然不是你想要的结果。
解决方案
根据你的需求,我提供两种常用的解决思路:
思路1:合并两种销售记录为单独行
如果你想把每个账户的面包销售、水销售记录分开展示(每条销售记录单独一行),可以用UNION ALL合并两个销售表,再和account关联:
SELECT a.ac, a.name, 'bread' AS sale_type, bs.amount AS sale_amount, bs.date AS sale_date FROM account a LEFT JOIN bread_sale bs ON a.ac = bs.ac UNION ALL SELECT a.ac, a.name, 'water' AS sale_type, ws.amount AS sale_amount, ws.date AS sale_date FROM account a LEFT JOIN water_sale ws ON a.ac = ws.ac ORDER BY a.ac, sale_date;
这个查询会把所有销售记录按账户、日期排序,每条记录清晰区分是面包还是水的销售,完全避免笛卡尔积问题。
思路2:按账户+日期汇总销售额
如果你想按账户+日期维度,同时展示当天的面包和水的总销售额,可以先对两个销售表做聚合子查询,再关联:
SELECT a.ac, a.name, COALESCE(bs.total_bread, 0) AS total_bread_amount, COALESCE(ws.total_water, 0) AS total_water_amount, COALESCE(bs.sale_date, ws.sale_date) AS sale_date FROM account a LEFT JOIN ( -- 聚合每个账户每天的面包销售额 SELECT ac, date AS sale_date, SUM(amount) AS total_bread FROM bread_sale GROUP BY ac, date ) bs ON a.ac = bs.ac LEFT JOIN ( -- 聚合每个账户每天的水销售额 SELECT ac, date AS sale_date, SUM(amount) AS total_water FROM water_sale GROUP BY ac, date ) ws ON a.ac = ws.ac AND bs.sale_date = ws.sale_date ORDER BY a.ac, sale_date;
这里用COALESCE把NULL值转换成0,避免空值显示;同时通过子查询提前聚合数据,再按账户和日期关联,彻底解决笛卡尔积导致的重复问题。
内容的提问来源于stack exchange,提问作者Anis
相关产品推荐
相关产品推荐

