如何获得链接到第三个表的两个表的总和

时间:2011-11-09 11:58:37

标签: mysql sql sql-server tsql postgresql

任何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的表现如此?

5 个答案:

答案 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的答案,可以帮助您了解最终获得此类结果的原因。对我来说唯一剩下的就是根据你的要求解释行为本身。

基本上,这种行为背后的原因是第二次加入不是在tbltypetblvalue上进行的,正如人们可能认为的那样,而是{{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值也是重复的。

因此,tblvaluetblcost中的行在此过程中会重复:

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

...或tblcosttblvalueid相关:

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