Consider a sales application where we have two tables SALES and INTERNAL_SALES.
- Table “SALES” references the number of transactions made by each sales person outside the company.
- Table “INTERNAL_SALES” references the number of transactions made by each sales person inside the company to another sales person.
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.
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.
Removing the intermediate aggregation and the unique sort should help a bit.