2011-11-09 35 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

感謝您的解釋! –

相關問題