Question

I have a table order_history that is similar to the following:

+-------------------------------------------------------------+
| order_history_id | order_id | order_status_id | date_addded |
+-------------------------------------------------------------+
| 1                | 1        | 1               | 2014-03-20  |
| 2                | 1        | 2               | 2014-03-21  |
| 3                | 1        | 3               | 2014-03-29  |
| 4                | 2        | 1               | 2014-03-20  |
| 5                | 2        | 2               | 2014-03-21  |
| 6                | 2        | 3               | 2014-04-02  |
| 7                | 3        | 1               | 2014-04-20  |
| 8                | 3        | 2               | 2014-04-21  |
| 9                | 3        | 3               | 2014-04-22  |
+-------------------------------------------------------------+

The order_status represents the status of an order

+-------------------------------+
| order_status_id | name        |
+-------------------------------+
| 1               | received    |
| 2               | processed   |
| 3               | shipped     |
+-------------------------------+

what i want to do is to pull out all the orders that have been received before 2014-04-01 but not shipped until after 2014-04-01.

So in this case the query would just return order_id 2 as this is the only order that was received before 2014-04-01 yet shipped after.

I can't even seem to get started... Any help, hints, or pointers much appreciated.

Was it helpful?

Solution

You can do so ,by joining your tables and count the statues shipped for each order by using expression in sum i.e SUM(os.name ='shipped') shipped

SELECT o.*
,SUM(os.name ='shipped') shipped
FROM 
orders o
LEFT JOIN orders_status os USING(order_status_id)
WHERE o.date_addded  < '2014-04-01'
GROUP BY o.order_id
HAVING shipped =0

Fiddle Demo

OTHER TIPS

You can use INNER JOIN with this, if I get what you really want you can try this:

SELECT DISTINCT order_id 
FROM order_history A
INNER JOIN order_status  B 
ON A.order_status_id = B.order_status_id
WHERE (A.order_Status_id = '1' AND A.date_added < @date) AND (A.order_status_id = '3' AND A.date_added < @date)
SELECT h1.order_id 
  FROM order_history h1 
  JOIN order_status s1 
    ON s1.order_status_id = h1.order_status_id  
  JOIN order_history h2 
    ON h2.order_id = h1.order_id 
  JOIN order_status s2
    ON s2.order_status_id = h2.order_status_id
 WHERE h1.date_addded < '2014-04-01' 
   AND s1.name = 'received'
   AND h2.date_addded >= '2014-04-01'
   AND s2.name = 'shipped';

Note: Too many 'd's in addded

SELECT r.order_id

FROM (
    SELECT DISTINCT oh.order_id
    FROM order_history AS oh
    JOIN order_status AS os ON(oh.order_status_id = os.order_status_id)
    WHERE os.name = 'received'
      AND oh.date_addded < '2014-04-01'
) AS r

JOIN (
    SELECT DISTINCT oh.order_id
    FROM order_history AS oh
    JOIN order_status AS os ON(oh.order_status_id = os.order_status_id)
    WHERE os.name = 'shipped'
      AND oh.date_addded > '2014-04-01'
) AS s ON (s.order_id = r.order_id)

demo

What about this simple and light query:

SELECT DISTINCT order_id 
FROM order_history o1 
JOIN order_history o2 
ON o1.order_id = o2.order_id 
AND o1.order_status_id=1 AND o1.date_added<'2014-04-01' 
AND o2.order_status_id=3 AND o2.date_added>'2014-04-01';

Not tested, but try this:

SELECT A.ORDER_ID
  FROM ORDER_HISTORY A, ORDER_HISTORY B
 WHERE A.ORDER_ID = B.ORDER_ID    
       AND A.order_status_id = 1
       AND A.date_addded < TO_DATETO_DATE ('2014-04-01', 'YYYY-MM-DD')
       AND B.order_status_id = 3
       AND B.date_addded > TO_DATETO_DATE ('2014-04-01', 'YYYY-MM-DD');
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top