2011-11-09 37 views
2

将任何SQL奇才在那里与这个问题帮助两个表的总和: 假设我有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

对于mysql非常类似的问题:http://stackoverflow.com/q/7989160/939860 –

回答

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中。加文的回答已经表明了一种方法。另一种方法是:

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 

...这可能会或可能不会,这取决于数据库引擎,您实际使用进行不同(可能会或可能不会更好)。

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`; 
+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; 
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 

...或者,如果tblcosttblvalue与相关:

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 
2

我想你已经有足够的答案建议如何正确解决你的问题。你也有@ araqnid的答案,可以帮助你了解为什么你最终得到这样的结果。根据你的要求,唯一留给我的似乎是解释行为本身。

基本上,后面这种行为的原因是第二个连接不执行上tbltypetblvalue,像一些人认为的事实,但对的结果tbltypetblcost之间的连接,一方面,和另一个是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

  • 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 

唯一的出路,你似乎是单独聚合每个表。这并不一定意味着单独的查询,只需将 sub查询分开,就像您现在可以从答案中看到的一样。

+0

感谢您的解释! –

相关问题