Exercise #30
This task is required to gather data from two tables in one resultant set so the income and the outcome in one point must be in one row.
Similar task (29) for Income_o and Outcome_o tables doesnt cause any problems as usual. The problem
s root is demonstrated by following solution.
Solution 2.1.1
SELECT Income.point, Income.date, SUM(out), SUM(inc)
FROM Income LEFT JOIN
Outcome ON Income.point = Outcome.point AND
Income.date = Outcome.date
GROUP BY Income.point, Income.date
UNION
SELECT Outcome.point, Outcome.date, SUM(out), SUM(inc)
FROM Outcome LEFT JOIN
Income ON Income.point = Outcome.point AND
Income.date = Outcome.date
GROUP BY Outcome.point, Outcome.date;
[[ column ]] |
---|
[[ value ]] |
The idea is in the joining of table with incomes and with outcomes by equality of point`s number and a date. Left join guarantees right result in case when there is some days with income only (outcome is NULL). Then it unions with an opposite query which has left join the outcomes table with the incomes table. This takes into account opposite situation when there is outcome and income is NULL. The duplicates are removed by UNION clause.
The query 2.1.1 returns wrong result if many income/outcome operations at one point happens in one day. As example for this situation we get typical day: March 24, 2001. Let`s execute a couple of queries:
SELECT * FROM Income
WHERE date = '2001-03-24 00:00:00.000' AND point = 1;
[[ column ]] |
---|
[[ value ]] |
SELECT * FROM Outcome
WHERE date = '2001-03-24 00:00:00.000' AND point = 1;
[[ column ]] |
---|
[[ value ]] |
We get such result:
Income
code | point | date | inc |
---|---|---|---|
3 | 1 | 2001-03-24 00:00:00.000 | 3600 |
11 | 1 | 2001-03-24 00:00:00.000 | 3400 |
Outcome
code | point | date | out |
---|---|---|---|
2 | 1 | 2001-03-24 00:00:00.000 | 3663 |
13 | 1 | 2001-03-24 00:00:00.000 | 3500 |
In case when there are both: incomes and outcomes, outer join and inner join are the same. Every single row from one table joins with every row from other one if the date and the points number are equal. That
s why before data is grouping such result would be returned (the income and outcome columns are only displayed):
inc | out |
---|---|
3600 | 3663 |
3600 | 3500 |
3400 | 3663 |
3400 | 3500 |
After grouping and summarizing we get doubling of the result as for income as well for outcome. If there would be three incomes, we would get tripling of outcome and so on.
The duplicates aren`t matter, because each query in union returns analogous result: there is only one row for each pair {point, date}.