I’ve a small database with 4 tables: Customer – Order – OrderLine – Product, I’m playing around a bit with queries and am trying to fetch the names of the people with the most expensive order.
After some playing around I’ve come up with the following query, which shows the prices of all orders:
SELECT SUM(OrderLine.Amount * Product.Price) AS OrderLinePrice, Orders.Id, Customer.Lastname
FROM OrderLine, Product, Orders, Customer
WHERE OrderLine.ProductId = Product.Id
AND Orders.Id = OrderLine.OrderId
AND Customer.Id = Orders.CustomerId
GROUP BY Orders.Id, Customer.Lastname
ORDER BY OrderLinePrice DESC
Now what I conceptually need to do, or think I need to do, is apply a MAX() to select only the highest OrderLinePrice, but I’m not succeeding with SQL Server complaining about not being able to perform aggregate functions on an expression that contains an aggregate…
=============== Update:
Currently my query looks like this:
SELECT t.CustomerLastName
FROM (
SELECT SUM(OrderLine.Amount * Product.Price) AS OrderLinePrice, Orders.Id, Customer.Lastname AS CustomerLastName
FROM OrderLine, Product, Orders, Customer
WHERE OrderLine.ProductId = Product.Id
AND Orders.Id = OrderLine.OrderId
AND Customer.Id = Orders.CustomerId
GROUP BY Orders.Id, Customer.Lastname
) AS t
WHERE t.OrderLinePrice =
(
SELECT MAX(s.OrderLinePrice) AS MaxOrderPrice
FROM (
SELECT SUM(OrderLine.Amount * Product.Price) AS OrderLinePrice, Orders.Id, Customer.Lastname AS CustomerLastName
FROM OrderLine, Product, Orders, Customer
WHERE OrderLine.ProductId = Product.Id
AND Orders.Id = OrderLine.OrderId
AND Customer.Id = Orders.CustomerId
GROUP BY Orders.Id, Customer.Lastname
) AS s
)
ORDER BY CustomerLastName
This retrieves a list of customers from which the price of their order is equal to the price of the most expensive order. This retrieves exactly what I want, but it feels horribly redundant.
How should I start making this more efficient (if possible)?
First of all, have you considered using explicit joins? It might just be a matter of taste, but perhaps you’ll find queries with explicit joins clearer than those with implicit ones (or “comma” joins), like in your example.
As for the question, you could use
TOP (1) WITH TIES, like this:Or you could use
RANK()orDENSE_RANK(), like this:If you are only interested in the topmost total price,
RANK()is enough, but if you ever want customers for topntotals, useDENSE_RANK()instead and change the condition fromrnk = 1tornk <= n.