views:

26

answers:

3

I have an orders table with a schema like this.

CREATE TABLE orders (
    order_id        int NOT NULL AUTO_INCREMENT,
    customer_id     int unsigned NOT NULL DEFAULT 0,
    order_date      int NOT NULL
)

I'm trying to retrieve a list of each customers most recent order. The table can have multiple orders by a customer, and each order has a primary key of order_id.

+1  A: 

As you use AUTO_INCREMENT for order_id the highest order_id per customer_id should be the latest:

Select customer_id, Max( order_id ) max_order_id
From orders
Group By customer_id

If you need all columns of that rows, you'd join a sub-select (edited to not depend on order_id):

Select o.customer_id, o.order_id, o.order_date
From orders o
Join (
    Select customer_id, Max( order_date ) max_order_date
    From orders
    Group By customer_id
) x On ( x.customer_id = c.customer_id AND x.max_order_date = o.order_date )
Peter Lang
This would probably work, but seems just a bit hacky to me...
Eric Petroelje
@Eric Petroelje: Why?
Peter Lang
+1 for a simple and clean query without subqueries. this query should work for most recent orders as well by changing order_id to order_date
PHP_Jedi
@Peter - because you are introducing two hidden dependencies - the first is that order_id is always increasing (what if it rolls over?) and the second is that the order_date cannot be changed (if it did, it would have no effect on the query). On the plus side, both of those things are pretty unlikely, and the performance of that query would likely be better than any alternative. Still scares me a bit though.
Eric Petroelje
@PHP_Jedi: Thanks. I assumed that orders are inserted in the order of `order_date`, if this is not the case, then your suggestion is right.
Peter Lang
Thanks, I didn't realize you can join on sub-selects like that.
Aglystas
@Eric Petroelje: Agreed, I edited the second part of my answer.
Peter Lang
+1  A: 
select o.*
from (
    select customer_id, max(order_date) as MaxOrderDate
    from orders
    group by customer_id
) om
inner join order o on om.customer_id = o.customer_id and om.MaxOrderDate = m.order_date
RedFilter
A: 

SELECT * FROM orders WHERE (customer_id, order_date) = (select customer_id, max(order_date) from orders group by customer_id)

Lloyd
This would work in oracle, but can you do that in MySQL?
Eric Petroelje
This query uses a subquery... subqueries may be slow if the subqeury result is large.
PHP_Jedi
I tested it in MySQL v5.1.41
Lloyd