我有练习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是结果加倍的结果。我在任何地方检查过,但我真的不明白。
答案 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