使用SUMs在子查询上使用LEFT OUTER JOIN进行查询

时间:2014-08-20 17:23:27

标签: sql postgresql sum left-join aggregate-functions

我尝试在相关表格上执行OUTER JOIN,但我希望JOIN SUM不是实际数据。这个查询是有缺陷的,所以我正在寻找这个结构的帮助,但我也很好奇,如果有一种更优雅的方式来执行这种类型的查询。

SELECT firstname,lastname, thesum1, thesum2 FROM whovians 
LEFT OUTER JOIN (
        SELECT SUM(thevalue) AS thesum1 FROM friends WHERE doctornumref = 10 AND year = 1968
    ) AS derivedTable1 
ON (whovians.doctornum = friends.doctornumref) 
LEFT OUTER JOIN (
        SELECT SUM(amount) AS thesum2 FROM enemies WHERE doctornumref = 10 AND year = 1968
    ) AS derivedTable2 
ON (whovians.doctornum = enemies.doctornumref) WHERE year = 1968 AND doctornum = 10;

1 个答案:

答案 0 :(得分:2)

应该像这样工作:

SELECT w.firstname, w.lastname, derived1.thesum1, derived2.thesum2
FROM   whovians w
LEFT   JOIN (
   SELECT doctornumref, SUM(thevalue) AS thesum1
   FROM   friends 
   WHERE  doctornumref = 10 
   AND    year = 1968
   GROUP BY 1
   ) AS derived1 ON derived1.doctornumref = w.doctornum
LEFT   JOIN (
   SELECT doctornumref, SUM(amount) AS thesum2 
   FROM   enemies 
   WHERE  doctornumref = 10 
   AND    year = 1968
   GROUP BY 1
   ) AS derived2 ON derived2.doctornumref = w.doctornum 
WHERE  w.doctornum = 10
AND    w.year = 1968;

在这种特殊情况下,由于您在外部查询和子查询中限制为相同的yeardoctornumref / doctornum,并且子查询只能返回0或1行,您可以使用低相关子查询进行简化:

SELECT firstname,lastname
      ,(SELECT SUM(thevalue)
        FROM   friends 
        WHERE  doctornumref = w.doctornum
        AND    year = w.year) AS thesum1
      ,(SELECT SUM(amount)
        FROM   enemies 
        WHERE  doctornumref = w.doctornum
        AND    year = w.year) AS thesum2
FROM   whovians w
WHERE  year = 1968
AND    doctornum = 10;

如果(year, doctornum)中的whovians不唯一,则第一个表单会阻止对子查询的重复评估,但效果会更好。

您仍然可以简化:

SELECT w.firstname, w.lastname, f.thesum1, e.thesum2
FROM   whovians w
LEFT   JOIN (
   SELECT SUM(thevalue) AS thesum1
   FROM   friends 
   WHERE  doctornumref = 10 
   AND    year = 1968
   ) f ON TRUE  -- 0 or 1 row in subquery, guaranteed to match
LEFT   JOIN (
   SELECT SUM(amount) AS thesum2 
   FROM   enemies 
   WHERE  doctornumref = 10 
   AND    year = 1968
   ) e ON TRUE
WHERE  w.doctornum = 10
AND    w.year = 1968;