views:

77

answers:

3

For example, I have a shop order database, and two tables in it - ORDERS and ORDERSTATUS.

Table : orders
--------------------------------------------
OrderID | OrderItems | AddedTimeStamp      |
--------------------------------------------
1       | Apples     | 2009-12-22 13:15:18 |
--------------------------------------------
2       | Bananas    | 2009-12-22 14:15:24 |
--------------------------------------------

Table : orderstatus
--------------------------------------------------------------------
StatusID | OrderID | Status   | AssignedUser | StatusTimestamp     |
--------------------------------------------------------------------
1        | 1       | Received | JohnSmith    | 2009-12-22 14:15:24 |
--------------------------------------------------------------------
2        | 2       | Received | MaryJane     | 2009-12-22 14:15:24 |
--------------------------------------------------------------------
3        | 1       | Process  | JohnSmith    | 2009-12-22 14:15:24 |
--------------------------------------------------------------------
4        | 2       | Process  | MaryJane     | 2009-12-22 14:15:24 |
--------------------------------------------------------------------
5        | 2       | Deliver  | MaryJane     | 2009-12-22 14:15:24 |
--------------------------------------------------------------------

I am running this SQL query :

SELECT od.orderid, od.orderitems, os.status, os.assigneduser
FROM orders AS od INNER JOIN orderstatus AS os
ON od.orderid = os.orderid
GROUP BY os.orderid
ORDER BY os.orderid ASC

This returns me :

------------------------------------------------
OrderID | OrderItems | Status   | AssignedUser |
------------------------------------------------
1       | Apples     | Received | JohnSmith    |
------------------------------------------------
2       | Bananas    | Received | MaryJane     |
------------------------------------------------

What I would like is :

------------------------------------------------
OrderID | OrderItems | Status   | AssignedUser |
------------------------------------------------
1       | Apples     | Process  | JohnSmith    |
------------------------------------------------
2       | Bananas    | Deliver  | MaryJane     |
------------------------------------------------

I'm quite new to MySQL queries, but I've been banging my head for the past 4 hours - can someone help?? TIA.

EDIT : The basic objective is I want to show the latest status for the orders.

+2  A: 

Its tough to get what you want without more information. All of the records in the orderstatus table have the same timestamp. It seems you just want the ones with the other status, but there isn't any way to differentiate the different statuses.

In order to do this, we need to tell MySQL how to pick the best row. Look closely... How would you know if you were a machine, which row to return?

The best I can guess is that you want the latest orderstatus record (max statusid). If that is the case, then here is a script that will work:

SELECT
    od.orderid, 
    od.orderitems, 
    os.status, 
    os.assigneduser
FROM orders AS od
INNER JOIN orderstatus AS os ON od.orderid = os.orderid
INNER JOIN (
    SELECT
        MAX(StatusID) AS StatusID,
        OrderId
    FROM orderstatus
    GROUP BY OrderId
) as maxos ON maxos.StatusID = os.StatusID
GROUP BY os.orderid
ORDER BY os.orderid ASC

I'm assuming your example is not accurate, and that the timestamp will actually be different in real life.

In that case, you can use the same script from above, but get the max(timestamp) instead of max(statusid).

The other thing you can do is normalize the status column (create a table for status codes, and add a column designating the order. Then you can get the max(that new order column) using the script above.

Gabriel McAdams
+1: Good call on using the statusid column.
OMG Ponies
@Gabriel - both yours and ponies's answer worked, but I voted yours as the answer because you attempted to find an alternative solution given the wrong data (timestamp) i gave in my question.**Kudos to the both of you anyway! Thanks so much, it works now, and I can stop banging my head!**
scoopdreams
+3  A: 

Use:

   SELECT o.orderid,
          o.orderitems,
          os.status,
          os.assigneduser
     FROM ORDERS o
LEFT JOIN ORDERSTATUS os ON os.orderid = o.orderid
     JOIN (SELECT os.orderid,
                  MAX(os.statustimestamp) 'm_statustimestamp'
             FROM ORDERSTATUS os
         GROUP BY os.orderid) x ON x.orderid = o.orderid
                               AND x.m_statustimestamp = os.status_timestamp

I used the timestamp as the way to find the latest record, though your data claims they will all be the same.

If you normalized your ORDERSTATUS.status column to a separate table (say ORDER_STATUS_CODE, with two columns - code and description), you'd have an easier time because assuming the use of an integer based key, you could use MAX() or MIN() depending on how the column was setup to get the highest status for a given order.

OMG Ponies
I would use the normalized approach with an ORDER_STATUS_CODE table.
kosoant
no no timestamps are different. :) the data i used here are copied-and-paste blindly. Will try your solution out, thanks!!
scoopdreams
+1 for having a solution that works as well. Thanks, ponies!
scoopdreams
A: 

Looks like you need to know the latest status and user per order. The join, group and order by will not work. You can achieve that result several ways and subqueries is one. Try this:

SELECT od.orderid, od.orderitems, 
(SELECT os.status FROM os.orderstatus AS os WHERE os.orderid = od.orderid ORDER BY os.StatusTimestamp LIMIT 1) AS status, 
(SELECT os.assigneduser FROM os.orderstatus AS os WHERE os.orderid = od.orderid ORDER BY os.StatusTimestamp LIMIT 1) AS assigneduser, 
FROM orders AS od

Take this with a grain of salt though. i don't know which version of MySql you're running and i'm more familiar with Sql Server than MySql. You might have to massage the query some.

Paul Sasik
Subselects?! *ewww* Anything will perform better than those.
OMG Ponies
Lol @ponies. (love the handle btw.) Subselects rock in Sql Server. And i refer you to either one of my two disclaimers in my answer... lol.
Paul Sasik
@Ponies: i see your answer above. Nice. i would run with it. i'm willing to bet that the Sql Server optimizer would turn my subquery example into something close to your answer sine logically there's little difference.
Paul Sasik