[英]how to get sum of two tables linked to a third
任何sql Wizards都会帮助解决这个问题:假设我有3个表:
tbltype tblvalue tblcost
id | type id | val | typeid id | cost| typeid
---------- ------------------ ------------------
1 | aaa 1 | 3 | 1 1 | 5 | 1
2 | bbb 2 | 2 | 1 2 | 3 | 1
3 | 2 | 2 3 | 1 | 2
4 | 1 | 2 4 | 4 | 2
当我运行此查询时:
SELECT t.type, SUM(val), SUM(cost)
FROM
tbltype t
LEFT JOIN tblcost c ON (c.typeid = t.id)
LEFT JOIN tblvalue v ON (v.typeid = t.id)
GROUP BY t.type;
我得到了错误的价值
type | SUM(val) | SUM(cost)
---------------------------
aaa | 10 | 16
bbb | 6 | 10
我如何获得正确的价值:
type | SUM(val) | SUM(cost)
---------------------------
aaa | 5 | 8
bbb | 3 | 5
为什么sql的表现如此?
SELECT t.type,
COALESCE((SELECT SUM(v.val) FROM tblvalue AS v WHERE v.typeid = t.id),0) AS val,
COALESCE((SELECT SUM(c.cost) FROM tblcost AS c WHERE c.typeid = t.id),0) AS cost
FROM tbltype AS t;
要了解原因,请从小组中总结并查看您的查询并查看它的总和:
SELECT t.type, val, cost
FROM
tbltype t
LEFT JOIN tblcost c ON (c.typeid = t.id)
LEFT JOIN tblvalue v ON (v.typeid = t.id)
你会看到输出中有来自tblcost和tblvalue的行的每种可能组合 - 这意味着当你将它们相加时,它们中的一些会被计数多次。
您需要分别聚合tblcost和tblvalue。 然后,您可以将它们连接回tbltype。 Gavin的回答已经显示了一种方法。 另一种方式是:
SELECT t.type, COALESCE(cost, 0) AS cost, COALESCE(val, 0) AS val
FROM tbltype t
LEFT JOIN (SELECT SUM(cost) AS cost, typeid FROM tblcost GROUP BY typeid) tc
ON tc.typeid = t.id
LEFT JOIN (SELECT SUM(val) AS val, typeid FROM tblvalue GROUP BY typeid) tv
ON tv.typeid = t.id
...根据您实际使用的数据库引擎,可能会执行或不执行(可能会也可能不会更好)。
我认为你有足够的答案建议如何正确解决你的问题。 您还得到了@ araqnid的答案,可以帮助您了解最终获得此类结果的原因。 对我来说,唯一剩下的就是根据你的要求解释行为本身。
基本上,这种行为背后的原因是第二次连接不是在tbltype
和tblvalue
上执行的,正如人们可能认为的那样,而是在tbltype
和tblcost
之间的连接结果,以及tblvalue
表,on另一个。 现在,第一个连接产生重复的t.id
,因为它们不止一次匹配第二个表:
tbltype tblcost
id type id cost typeid t.id t.type c.id c.cost c.typeid
-- ---- × -- ---- ------ = ---- ------ ---- ------ --------
1 aaa 1 5 1 1 aaa 1 5 1
1 bbb 2 3 1 1 aaa 2 3 1
3 1 2 2 bbb 3 1 2
4 4 2 2 bbb 4 4 2
第二个连接产生更多重复,因为:
t.id
从第一个加入的结果集对是越来越匹配v.typeid
和
tblvalue
表中的typeid
值也是重复的。 结果,来自tblcost
和tblvalue
进程中重复:
tblvalue
t.id t.type c.id c.cost c.typeid id val typeid
---- ------ ---- ------ -------- -- --- ------
1 aaa 1 5 1 × 1 3 1 =
1 aaa 2 3 1 2 2 1
2 bbb 3 1 2 3 2 2
2 bbb 4 4 2 4 1 2
t.id t.type c.id c.cost c.typeid v.id v.val v.typeid
---- ------ ---- ------ -------- ---- ----- --------
1 aaa 1 5 1 1 3 1
1 aaa 1 5 1 2 2 1
= 1 aaa 2 3 1 1 3 1
1 aaa 2 3 1 2 2 1
2 bbb 3 1 2 3 2 2
2 bbb 3 1 2 4 1 2
2 bbb 4 4 2 3 2 2
2 bbb 4 4 2 4 1 2
唯一的出路似乎是分别聚合每个表。 queries, as you can now see from the answers. 这并不一定意味着单独的查询,只是单独的查询,正如您现在可以从答案中看到的那样。
最快的解决方案是将查询拆分为两个
SELECT
`tbltype`.`type`, SUM(val)
FROM
tbltype
LEFT JOIN `tblvalue` ON (`tblvalue`.`typeid` = `tbltype`.`id`)
GROUP BY `tbltype`.`type`;
和
SELECT
`tbltype`.`type`, SUM(cost)
FROM
tbltype
LEFT JOIN `tblcost` ON (`tblcost`.`typeid` = `tbltype`.`id`)
GROUP BY `tbltype`.`type`;
像这样的东西:
select t1.id, val, cost from (
select t.id, sum(val) as val
from tbltype t
join tblvalue v on t.id = v.typeId
group by t.id
) t1
join (
select t.id, sum(cost) as cost
from tbltype t
inner join tblcost c on t.id = c.typeid
group by t.id
) t2 on t1.id = t2.id
...或者如果tblcost
和tblvalue
与id
相关:
select t.id, sum(val) as val, sum(cost) as cost
from tbltype t
inner join tblcost c on t.id = c.typeid
inner join tblvalue v on c.id = v.id
group by t.id
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.