tags:

views:

69

answers:

3

Suppose I have a table Orders in sql with 4 columns (OrderId int, ProductID int, Price money, Size int) with OrderID and ProductID as a joint primary key.

If I want a query to return the most recent order (along with price and size) for every product (i.e., maximal OrderId) is there a way to do this without a join?

I was thinking of the following:

select o.OrderId, o.ProductId, o.Price, o.Size
from Orders o inner join 
(select Max(OrderId) OrderId, ProductId from Orders group by ProductId) recent
on o.OrderId = recent.OrderId and o.ProductId = recent.ProductId

but this doesn't seem like the most elegant solution possible.

Also, assume that an order with multiple products generates multiple rows. They are both necessarily part of the primary key.

A: 
select
 MAX(o.OrderId) as NewestOrderID,
 o.ProductId,
 o.Price,
 o.Size
from Orders o
Group by
 o.ProductId,
 o.Price,
 o.Size
Sage
but that returns all distinct (productId, price, size) tuples, which isn't what I wanted
chuck taylor
true enough. I personally employ the pattern you use above quite frequently and rarely have issues with it, from a performance perspective.
Sage
A: 

But if OrderID and ProductID are your PK as you state then it doesn't matter if it's all distant because ProductID will never repeat within an OrderID.

shuff1203
This should be a comment not an answer.
Chris
Its also wrong. If both columns are jointly a primary key, values of (1, 1), (1, 2), (2, 1), and (2, 2) are valid.
Drew McGhie
+2  A: 

No, there isn't. You've got the right idea. You need to do the subquery to get the max(orderID), productID pair, and then join that to the full table to limit the query to the rows in the full table that contain the max OrderId.

Drew McGhie
I agree there can't be a way to do this with an aggregator function and a group by, but this seems like a pretty common problem that I have run into a few times so I was optimistic there might be a clever way to frame it as an apply or something like that.
chuck taylor
This is basically the clever way. I do basically the same thing with email addresses and activity dates on a few tables I manage, grouping by email to get the most recent activity, and then re-joining to get all the information for those rows. I can understand the desire for more nuanced/efficient solutions, but in this case, there isn't one.
Drew McGhie