ProfFansyPants
ProfFansyPants

Reputation: 29

SQL Server Aggregation using Max() and obtaining details from max() line.

I just took a final exam and one of the questions asked me to double join three tables, and report the max sale payout for each salesperson. The tables have the following variables:

Salesperson(id, name) Order(orderid, order_date, Cust_id, Saleperson_id, amount) Customer(id, name)

After joining:

select salesperson.Name, Orders.Number, customer.Name, Orders.Amount
from Orders
join salesperson
on orders.Salesperson_id = salesperson.ID
join Customer
on customer.ID = orders.cust_id

What the instructed wanted was for me to find each salesperson's maximum sell (as found by order.amount). He also wanted the salesperson (salesperson.name), the order number of the max sale (orders.number), the customer the sale was with (customer.name), and the max sale amount. What is the most efficient way to do this problem? I have tried to use "group by salesperson.name", but I cannot because the orders.number and customer.name are never held in the aggregation.

I finished the problem this way

select 
salesperson.name as Sales_Person, 
orders.number as Order_Number, 
customer.Name as Customer_Name, 
orders.Amount as Sale_Amount
from salesperson
left join Orders
on salesperson.ID = orders.Salesperson_id
left join Customer
on orders.cust_id = customer.ID
where orders.Amount in (select max(orders.Amount)
  from salesperson
  join Orders
  on salesperson.ID = orders.Salesperson_id
  join Customer
  on orders.cust_id = customer.ID
  group by salesperson.name)

I know this is a bad way to do it. For instance, what if two different salesperson's max sale was equivalent? Max and min are not like count and sum because it is picking out one line from a aggregation, but the rules still apply. Also, you might notices that there is no real unique identifier in the joined table other than order.number which is not useful. Therefore, I would have to use some composite of salesperson.name and order.number.

Also, what do I do if I have to pick the top three sales for each salesperson? Should such an output be totally different code-wise than what would be required from just the first sale?

I keep bumping me head against this problem, and I would love to have a more professional approach to this problem.

Upvotes: 1

Views: 753

Answers (1)

Anon
Anon

Reputation: 10918

SELECT
    M.max_amount,
    S.Name,
    O.Number,
    C.Name
FROM orders O
JOIN salesperson S
    ON S.Salesperson_id = O.Salesperson_id
JOIN customer C
    ON C.Customer_id = O.Customer_id
JOIN (
    SELECT Salesperson_id, MAX(amount) max_amount
    FROM Order
    GROUP BY Salesperson_id
) M
    ON M.Salesperson_id = O.Salesperson_id AND M.max_amount = O.amount

For the top 3:

SELECT
    M.Amount,
    S.Name,
    O.Number,
    C.Name
FROM orders O
JOIN salesperson S
    ON S.Salesperson_id = O.Salesperson_id
JOIN customer C
    ON C.Customer_id = O.Customer_id
CROSS APPLY (
    SELECT TOP 3 Amount
    FROM Order
    WHERE Salesperson_id = O.Salesperson_id
    ORDER BY Amount DESC
) M

Upvotes: 2

Related Questions