任何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的表现如此?
答案 0 :(得分:3)
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;
答案 1 :(得分:3)
要了解原因,请小组并总结您的查询并查看它的总和:
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
...根据您实际使用的数据库引擎,可能会执行或不执行(可能会也可能不会更好)。
答案 2 :(得分:2)
我认为你有足够的答案建议如何正确解决你的问题。您还得到了@ araqnid的答案,可以帮助您了解最终获得此类结果的原因。对我来说唯一剩下的就是根据你的要求解释行为本身。
基本上,这种行为背后的原因是第二次加入不是在tbltype
和tblvalue
上进行的,正如人们可能认为的那样,而是{{1}之间的联接结果一方面是tbltype
,另一方面是tblcost
表。现在,第一个连接产生重复的tblvalue
,因为它们不止一次匹配第二个表:
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
表中的typeid
值也是重复的。因此,tblvalue
和tblcost
中的行在此过程中会重复:
tblvalue
唯一的出路似乎是分别聚合每个表。这并不一定意味着单独的查询,只是单独的 sub 查询,正如您现在可以从答案中看到的那样。
答案 3 :(得分:0)
最快的解决方案是将查询拆分为两个
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`;
答案 4 :(得分:0)
这样的事情:
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