左联接的SQL Double结果与分组

时间:2016-04-29 16:47:49

标签: sql sql-server postgresql

我有练习30:

  

假设每个收集点每天可以多次登记货币(公司)和支出(外出)的收据[即代码列是主键],显示每个集合点的每个操作日期具有一个对应行的表。   结果集:点数,日期,每日总支出(输出),每日总支出(inc)。   缺少的值被视为NULL。

schema of database(其回收公司) 这是我的代码:

WITH IO_table
AS
(SELECT point, "date" FROM Income
UNION
SELECT point, "date" FROM Outcome)

SELECT io.point, io.date, SUM(o.out), SUM(i.inc)
FROM IO_table io
LEFT OUTER JOIN Income i ON io.point = i.point AND io."date" = i."date" 
LEFT OUTER JOIN Outcome o ON io.point = o.point AND io."date" = o."date"
GROUP BY
io.point, io.date

Here是结果加倍的结果。我在任何地方检查过,但我真的不明白。

3 个答案:

答案 0 :(得分:0)

目前无法区分IO_table中的收入和结果。所以你要两次添加每个值,一次是收入,一次是结果。解决此问题的一种方法是在IO_table中添加另一列以区分这两列,然后更新join语句以包含新列。

答案 1 :(得分:0)

这就是为什么你的总和是多方面的:让我们说同一个日期和点有两个收入记录,包含inc 150和250,三个结果记录包含100,200和300.你加入这些记录,所以你得到了对150-100,150-200,150-300,250-100,250-200,250-300。现在你聚合并求和:这使得inc = 3 x(150 + 250)= 1200和out = 2 x(100 + 200 + 300)= 1200而不是所需的inc = 400且out = 600。

当需要来自不同表的聚合时,不要加入表,而是加入聚合,例如:

LEFT OUTER JOIN
(
  select point, "date", sum(inc) as total
  from Income 
  group by point, "date"
) i ON io.point = i.point AND io."date" = i."date" 

在您的情况下,您需要两个聚合的完全外连接:

select 
  point, 
  "date", 
  coalesce(i.total, 0) as inc_total, 
  coalesce(o.total, 0) as out_total
from
(
  select point, "date", sum(inc) as total
  from income 
  group by point, "date"
) i
full outer join
(
  select point, "date", sum(out) as total
  from outcome 
  group by point, "date"
) o using(point, "date");

这是在PostgreSQL中使用的标准SQL。对于SQL Server,您需要[date]而不是标准"date"ON clause而不是简单的USING子句。

答案 2 :(得分:-1)

我猜这就是你要找的东西:

SELECT X.POINT,X.DATE,SUM(OUT),SUM(INC) FROM (
    SELECT I.POINT,I.DATE,0 AS OUT, SUM(I.INC) AS INC FROM INCOME I
    GROUP BY I.POINT,I.DATE
    UNION 
    SELECT O.POINT,O.DATE,SUM(O.OUT) AS OUT , 0 AS INC FROM OUTCOME O
    GROUP BY O.POINT,O.DATE) AS X
GROUP BY POINT,DATE