繁体   English   中英

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

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

基本上,这种行为背后的原因是第二次连接不是在tbltypetblvalue上执行的,正如人们可能认为的那样,而是在tbltypetblcost之间的连接结果,以及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值也是重复的。

结果,来自tblcosttblvalue进程中重复:

                                           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

...或者如果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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM