我想加入3个表并从其中2个表中汇总两列的记录,同时避免记录重复

时间:2014-02-11 16:23:30

标签: sql postgresql

假设我有3个表

A:

---------------
  id  |  name 
---------------
   1  |   A
---------------
   2  |   B
---------------

B:

-----------------------
  id  |  val   | A_id
-----------------------
   1  |  10    |  1
-----------------------
   2  |  20    |  2
-----------------------
   3  |  30    |  2
-----------------------

C:

-----------------------
  id  |  val   | B_id
-----------------------
   1  |  40    |  2
-----------------------
   2  |  50    |  2
-----------------------
   3  |  60    |  2
-----------------------

我如何得到这个结果:

----------------------------
  A_name  | B_val  | C_val
----------------------------
     A    |  10    |   0
----------------------------
     B    |  50    |  150
----------------------------

我试过这样做:

SELECT A.name, SUM(COALESCE(B.val,0)), SUM(COALESCE(C.val,0)) 
FROM A
LEFT JOIN B ON A.id = B.A_id
LEFT JOIN C ON B.id = C.B_id
GROUP BY A

但它却改为:

----------------------------
  A_name  | B_val  | C_val
----------------------------
     A    |  10    |   0
----------------------------
     B    |  90    |  150
----------------------------

我想这是因为C有3条与B相关的记录,所以B的第二条记录乘以3。获得我想要的结果的最佳方法是什么?

3 个答案:

答案 0 :(得分:0)

将查询拆分为两个,然后将这些子查询用作第三个子查询的数据源:

-- The first query (it returns the sum of b.val)
select a.id, a.name, sum(b.val) as sum_b_val
from a left join b on a.id = b.a_id
group by a.id;

-- The second query (it returns the sum of c.val)
select b.a_id, sum(c.val) as sum_c_val
from b left join c on b.id = c.b_id
group by b.a_id;

-- Put it all together
select
  q1.name, 
  coalesce(q1.sum_b_val, 0) as sum_b_val, 
  coalesce(q2.sum_c_val, 0) as sum_c_val
from
  (
    select a.id, a.name, sum(b.val) as sum_b_val
    from a left join b on a.id = b.a_id
    group by a.id
  ) as q1
  left join (
    select b.a_id, sum(c.val) as sum_c_val
    from b left join c on b.id = c.b_id
    group by b.a_id
  ) as q2 on q1.id = q2.a_id;

检查this example on SQL Fiddle

希望这有帮助

答案 1 :(得分:0)

将计算移动到子选择中:

select tablea.id, tablea.name, B.B_val, C.C_val FROM tablea
LEFT JOIN
(select tablea.id AS id, SUM(COALESCE(tableb.val,0)) as B_val
from tablea left join tableb on tablea.id = tableb.A_id
group by tablea.id) AS B ON tablea.id = B.id
LEFT JOIN
(select tablea.id AS id, SUM(COALESCE(tablec.valc,0)) as C_val
from tablea left join tableb on tablea.id = tableb.A_id
left join tablec on tablec.B_id = tableb.id
group by tablea.id) AS C on tablea.id = C.id 

http://sqlfiddle.com/#!2/4c268/14

编辑,我为MySQL设置了SQL Fiddle。代码没有任何变化,但这里是postgres http://sqlfiddle.com/#!15/4c268/1

答案 2 :(得分:0)

只有当表A中的id是唯一的时,查询才会起作用。

select t1.name,t1.bval,t2.cval from 
 (select A.id, A.name, SUM(ISNULL(B.val,0)) bval
  from A
  left join b on a.id = b.A_id
  group by A.id, A.name) t1
left join
 (select B.A_Id, sum(ISNULL(c.val,0)) cval 
  from B
  left join c on b.id = c.b_id
  group by A_ID) t2
on t1.id = t2.A_Id;