Reputation: 223
Consider a sales application where we have two tables SALES and INTERNAL_SALES.
SALES Table: Each date has one entry against each sales person even if transactions are zero.
id | day | sales_person | number_of_transactions 1 | 2011-08-01 | Tom | 1000 2 | 2011-08-01 | Ben | 500 3 | 2011-08-01 | Anne | 1500 4 | 2011-08-02 | Tom | 0 5 | 2011-08-02 | Ben | 800 6 | 2011-08-02 | Anne | 900 7 | 2011-08-03 | Tom | 3000 8 | 2011-08-03 | Ben | 0 9 | 2011-08-03 | Anne | 40
INTERNAL_SALES Table: This table logs only the transactions that were actually made between sales persons.
id | day | sales_person_from | sales_person_to | number_of_transactions 0 | 2011-08-01 | Tom | Ben | 10 1 | 2011-08-01 | Tom | Anne | 20 2 | 2011-08-01 | Ben | Tom | 50 3 | 2011-08-03 | Anne | Tom | 30 4 | 2011-08-03 | Anne | Tom | 30
Now the problem is to come up with total transactions by each sales person on a daily basis. The way I did this is:
SELECT day, sales_person, sum(num_transactions) from ( SELECT day, sales_person, number_of_transactions As num_transactions FROM sales; UNION SELECT day, sales_person_from As sales_person, sum(number_of_transactions) As num_transactions FROM internal_sales GROUP BY day, sales_person_from; ) GROUP BY day, sales_person;
This is too slow and looks ugly. I am seeking a better solution. By the way the database being used in Oracle and I have no control over database except that I can run queries against it.
Upvotes: 3
Views: 152
Reputation: 23972
There is no need to aggregate twice, and the union operator typically does an implicit unique sort which, again, in not necessary in your case.
SELECT day, sales_person, sum(num_transactions) from
(
SELECT day, sales_person, number_of_transactions As num_transactions FROM sales;
UNION ALL
SELECT day, sales_person_from, number_of_transactions FROM internal_sales;
)
GROUP BY day, sales_person;
Removing the intermediate aggregation and the unique sort should help a bit.
Upvotes: 7