imtiaz
imtiaz

Reputation: 223

Nested query - looking for better solution

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

Answers (1)

Code Magician
Code Magician

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

Related Questions