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.

Était-ce utile?

La 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

Autres conseils

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');
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top