Seleccione el estado del último pedido de Pedidos

Tengo mesas:

pedidos:

id_order    id_customer    
1           1              
2           2              
3           1              

orders_history

id_history  id_order    id_order_state    date_add
1           1           1                 2010-01-01 00:00:00
2           1           2                 2010-01-02 00:00:00
3           1           3                 2010-01-03 00:00:00
4           2           2                 2010-05-01 00:00:00
5           2           3                 2011-05-02 00:00:00
6           3           1                 2011-05-03 00:00:00
7           3           2                 2011-06-01 00:00:00

order_state

id_order_state    name
1                 New
2                 Sent
3                 Rejected
4                 ...

¿Cómo obtener todos los order_id's donde el último id_order_state de ese pedido (por último me refiero a que con MAX (id_history) o MAX (date_add)) no es igual a 1 o 3?

preguntado el 16 de mayo de 11 a las 17:05

¿Puedes publicar la salida deseada? -

4 Respuestas

Creo que lo que busca es qué pedidos están completos ... es decir, su estado final, no los que son exclusivos del 1 y 3 específicamente. La primera consulta previa debe ser el ID máximo independientemente del código de estado

select 
      orders.*
   from
      ( select oh.id_order, 
               max( oh.id_history ) LastID_HistoryPerOrder
           from
               orders_history oh
           group by
               oh.id_order ) PreQuery
      join orders_history oh2
         on PreQuery.ID_Order = oh2.id_order
         AND PreQuery.LastID_HistoryPerOrder = oh2.id_history
         AND NOT OH2.id_order_state IN (1, 3)   <<== THIS ELIMINATES 1's & 3's from result set
      join Orders                               <<= NOW, anything left after above ^ is joined to orders
         on PreQuery.ID_Order = Orders.ID_Order

Solo para volver a mostrar SUS datos ... He marcado la última SECUENCIA (ID_History) por ORDEN ... Esto es lo que la PREQUERY va a devolver ...

id_history  id_order    id_order_state    date_add
  1           1          1                2010-01-01 00:00:00
  2           1          2                2010-01-02 00:00:00   
**3           1          3                2010-01-03 00:00:00

  4           2          2                2010-05-01 00:00:00   
**5           2          3                2011-05-02 00:00:00

  6           3          1                2011-05-03 00:00:00   
**7           3          2                2011-06-01 00:00:00

La "PreQuery" resultará con el siguiente subconjunto

ID_Order   LastID_HistoryPerOrder (ID_History)
1          3  (state=3)  THIS ONE WILL BE SKIPPED IN FINAL RESULT
2          5  (state=3)  THIS ONE WILL BE SKIPPED IN FINAL RESULT
3          7  (state=2)

Ahora, el resultado de esto se vuelve a unir al historial de pedidos solo en estos dos elementos ... sin embargo, agrega los criterios para EXCLUIR las 1,3 entradas para el "estado del pedido".

En este caso,

   1 would be rejected as its state = 3 (sequence #3), 
   2 would be rejected since its last history is state = 3 (sequence #5).  
   3 would be INCLUDED since its state = 2 (sequence #7)  

Finalmente, todo lo que se unió a los pedidos resultará con UNA ID, y coincidirá muy bien con la tabla de pedidos en el Order_ID solo y obtendrá los resultados deseados.

contestado el 17 de mayo de 11 a las 01:05

@DRapp pero para id_order = 2 debería devolver 3 como último id_order_state. Para id_order = 3 debería devolver 2. - Dariusz

@dario, vuelva a revisar esta respuesta. Cambié el nombre de la columna de resultados de la preconsulta para ayudar a aclarar lo que quise decir originalmente con "LastSequence". Ahora es "LastID_HistoryPerOrder". Además, en la consulta final, tengo dos << == líneas de comentario que deberían eliminarse. Estos son para ayudar a aclarar CUÁNDO se eliminan los 1 y 3. - DRapp

@DRapp Por favor, eche un vistazo a mi publicación con los resultados de su consulta. - Dariusz

@Dario, publicaste mal mi consulta en dos partes ... La cláusula NOT IN debería haber estado NO EN oh2.id_order_state IN (1,3) ... solo tenías (3). A continuación, el grupo por INNER PRE QUERY ... Tiene el pedido por el HISTORY ID ... Nop .. Solo el ID_ORDER y obtendrá lo que está esperando ... De hecho lo probé con sus datos y consiguió lo que se esperaba ... un registro ... orden # 3 - DRapp

select oh.id_history, oh.id_order, oh.id_order_state, oh.date_add
from (
    select id_order, max(date_add) as MaxDate
    from orders_history
    where id_order_state not in (1, 3)
    group by id_order 
) ohm
inner join orders_history oh on ohm.id_order = oh.id_order 
    and ohm.MaxDate = oh.date_add

contestado el 16 de mayo de 11 a las 22:05

Como referencia, este tipo de problema a menudo se conoce como el problema del "máximo en grupo". - TehShrike

@TehShrike Strange pero no obtengo el resultado adecuado: creo que hay un problema para obtener la fecha MAX. Lo mismo con @Tom H. respuesta. - Dariusz

@dario ¿cuál es el tipo de datos del date_add ¿columna? - D'Arcy Rittich

@dario - No puedo ayudarte entonces, o algo está profundamente roto o estás consultando una base de datos / tabla diferente de la que crees ... - D'Arcy Rittich

@RedFilter Puedo darte acceso phpmydamin para probar db si tienes algo de tiempo. - Dariusz

Otra posible solución:

SELECT DISTINCT
    id_order
FROM
    Orders_History OH1
LEFT OUTER JOIN Orders_History OH2 ON
    OH2.id_order = OH1.id_order AND
    OH2.is_order_state IN (1, 3) AND
    OH2.date_add >= OH1.date_add
WHERE
    OH2.id_order IS NULL

contestado el 16 de mayo de 11 a las 22:05

Por ejemplo, para establecer que tiene: date_add: 2011-05-11 22:36:20 y 2011-04-16 23:21:24 me da el segundo como fecha máxima y luego el id_state incorrecto - Dariusz

No estoy seguro de lo que quiso decir con eso, pero si intentaba utilizar el método LEFT JOIN para encontrar valores extremos, creo que se equivocó un poco. Debería ser ...ON OH2.id_order = OH1.id_order AND OH2.date_add > OH1.date_add WHERE OH1.is_order_state NOT IN (1, 3) AND OH2.id_order IS NULL. - Andriy M

@ andriy-m ¡Tienes razón! @ Tom-h, por favor corrija su respuesta como dijo andriy-m y estará terminado :) - Dariusz

Estoy usando "responder a mi pregunta" porque necesito publicar los resultados de sus consultas. Entonces.

Desafortunadamente, no todas sus respuestas funcionan. Preparemos el entorno de prueba:

CREATE TABLE `order_history` (
`id_order_history` int(11) NOT NULL AUTO_INCREMENT,
`id_order` int(11) NOT NULL,
`id_order_state` int(11) NOT NULL,
`date_add` datetime NOT NULL,
PRIMARY KEY (`id_order_history`)
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=latin2;

CREATE TABLE `orders` (
`id_order` int(11) NOT NULL AUTO_INCREMENT,
`id_customer` int(11) DEFAULT NULL,
PRIMARY KEY (`id_order`)
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=latin2;

INSERT INTO `order_history` 
(`id_order_history`, `id_order`, `id_order_state`,     `date_add`) VALUES 
(1,1,1,'2011-01-01 00:00:00'),
(2,1,2,'2011-01-01 00:10:00'),
(3,1,3,'2011-01-01 00:20:00'),
(4,2,1,'2011-02-01 00:00:00'),
(5,2,2,'2011-02-01 00:25:01'),
(6,2,3,'2011-02-01 00:25:59'),
(7,3,1,'2011-03-01 00:00:01'),
(8,3,2,'2011-03-01 00:00:02'),
(9,3,3,'2011-03-01 00:01:00'),
(10,3,2,'2011-03-02 00:00:01');
COMMIT;

INSERT INTO `orders` (`id_order`, `id_customer`) VALUES 
(1,1),
(2,2),
(3,3),
(4,4),
(5,5),
(6,6),
(7,7);
COMMIT;

Ahora, seleccionemos Último / Estado máximo para cada pedido, así que ejecutemos una consulta simple:

 select id_order, max(date_add) as MaxDate
 from `order_history`
 group by id_order

esto nos da resultados APROPIADOS, sin ciencia espacial en este momento:

id_order         MaxDate
---------+-------------------
1         2011-01-01 00:20:00  //last order_state=3
2         2011-02-01 00:25:59  //last order_state=3
3         2011-03-02 00:00:01  //last order_state=2

Ahora por simplicidad, no sea que cambiar nuestras consultas para obtener pedidos donde Last State no es igual a 3.

Esperamos obtener un resultado de fila con id_order = 3.

Así que probemos nuestras consultas:

CONSULTA 1 realizada por RedFilter:

select oh.id_order, oh.id_order_state, oh.date_add
from (
    select id_order, max(date_add) as MaxDate
    from `order_history`
    where id_order_state not in (3)
    group by id_order
) ohm
inner join `order_history` oh on ohm.id_order = oh.id_order 
and ohm.MaxDate = oh.date_add

Resultado:

id_order    id_order_state    date_add
-------------------------------------------------
1           2                 2011-01-01 00:10:00
2           2                 2011-02-01 00:25:01
3           2                 2011-03-02 00:00:01

Entonces es no es cierto

CONSULTA 2 realizada por Tom H.:

SELECT DISTINCT OH1.id_order
FROM order_history OH1
LEFT OUTER JOIN order_history OH2 ON
  OH2.id_order = OH1.id_order AND
  OH2.id_order_state NOT IN (3) AND
  OH2.`id_order_history` >= OH1.`id_order_history`
WHERE
  OH2.id_order IS NULL

Resultado:

id_order
--------
1
2

Entonces es no es cierto

Cualquier sugerencia apreciada.

EDITAR

Gracias a Andriy M. comentar tenemos solución adecuada. Es una modificación de la consulta de Tom H., todo debería verse de la siguiente manera:

SELECT DISTINCT
OH1.id_order
FROM
  order_history OH1
LEFT OUTER JOIN order_history OH2 ON
  OH2.id_order = OH1.id_order
AND OH2.date_add > OH1.date_add 
WHERE OH1.id_order_state NOT IN (3) AND OH2.id_order IS NULL

EDIT 2:

CONSULTA 3 realizada por DRapp:

select
  distinct orders.`id_order`
from
  ( select oh.id_order,
           max( oh.id_order_history ) LastID_HistoryPerOrder
       from
           order_history oh
       group by
           oh.id_order ) PreQuery
  join order_history oh2
     on PreQuery.id_order = oh2.id_order
     AND PreQuery.LastID_HistoryPerOrder = oh2.id_order_history
     AND NOT oh2.id_order_state IN (1,3)  
join orders                              
  on PreQuery.id_order = orders.id_order

Resultado:

id_order
--------
3

Así que finalmente es verdadero

respondido 01 nov., 15:15

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.