tags:

views:

163

answers:

4

Using SQL (MySQL) only I would like to select each of the last child rows of a parent child relationship where the child rows are ordered by a timestamp.

For example using the tables invoices and invoice_items, I want the newest (ie: most recently timestamped) invoice_items records for each invoice respectively.

--------------------------
|Invoices                |
--------------------------
|invoice_id| other fields|
--------------------------
| 1        | ...         |
--------------------------
| 2        | ...         |
--------------------------
| 3        | ...         |
--------------------------

--------------------------------------------
|Invoice_Items                             |
--------------------------------------------
| id | invoice_id | invoice_item_timestamp |
--------------------------------------------
| 1  | 1            | 2009-12-01 10:00:00  |
--------------------------------------------
| 2  | 1            | 2009-12-01 10:01:00  |
--------------------------------------------
| 3  | 1            | 2009-12-01 10:02:00  |
--------------------------------------------
| 4  | 2            | 2009-12-01 9:00:00   |
--------------------------------------------
| 5  | 3            | 2009-12-02 08:30:00  |
--------------------------------------------
| 6  | 3            | 2009-12-03 08:31:00  |
--------------------------------------------

What is the best SQL syntax to produce a resultset that would look something like the following table?

-----------------------------------------------------
|invoice_id| invoice_item_id |invoice_item_timestamp|
---------------------------------------------------
| 1        | 3               | 2009-12-01 10:02:00  |
| 2        | 4               | 2009-12-01 09:00:00  |
| 3        | 6               | 2009-12-03 08:31:00  |
-----------------------------------------------------
A: 

I would think that something like this would work:

select i.invoice_id, ii.id, ii.invoice_item_timestamp from invoices i left join invoice_items ii on ii.invoice_id = i.invoice_id
 where ii.invoice_item_timestamp = 
   (select max(ii2.invoice_item_timestamp) from invoice_items ii2 where ii2.invoice_id = ii.invoice_id)
BryanD
+1  A: 

I don't use MySQL, but you'll get the idea:

select 
  invoices in

  inner join invoice_items it
  on in.invoice_id = it.invoice_id
  and invoice_item.invoice_item_id =
     (select max(invoice_item_id) from invoice_item 
        where invoice_id = in.invoice_id)

... assuming there are no duplicates of invoice_item_id and invoice_id in the invoice_item table.

cdonner
A: 

You could try this (untested):

SELECT a.*
FROM Invoices a, invoice_items b
WHERE a.invoice_id = b.invoice_id 
ORDER BY invoice_item_timestamp DESC
LIMIT 1
Steven
This does not work. The LIMIT clause causes the recordset to return only one record. In the example you've provided it would return the one record with the highest PersonID. I am looking for the last child record of all parents repectively.
rswolff
+5  A: 
SELECT i.*,it.* 
FROM invoices i
INNER JOIN (
 SELECT invoice_id, MAX(invoice_item_timestamp) 
 FROM invoice_items
 GROUP BY invoice_id
) it ON (i.invoice_id=it.invoice_id)
Patrick