Выберите последнее состояние заказа из заказов - PullRequest
2 голосов
/ 16 мая 2011

У меня есть таблицы:

заказов:

id_order    id_customer    
1           1              
2           2              
3           1              

история заказов

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

состояние заказа

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

Как получить, где все order_idпоследнее id_order_state этого порядка (под последним я имею в виду это с MAX (id_history) или MAX (date_add)) не равно 1 или 3?

Ответы [ 4 ]

4 голосов
/ 16 мая 2011
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
1 голос
/ 16 мая 2011

Я думаю, что он после того, какие заказы завершены ... т.е. их окончательный статус, а не те, которые исключают 1 и 3 конкретно.Первым предварительным запросом должен быть максимальный идентификатор независимо от кода состояния

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

Просто для повторного показа ВАШИХ данных ... Я отметил последний SEQUENCE (ID_History) для ЗАКАЗА ... Этоэто то, что будет возвращать PREQUERY ...

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

Результатом "PreQuery" будет следующее подмножество

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)

Теперь результат этого затем снова объединяетсявернуться к истории заказов только по этим двум элементам ... но добавляет критерии для ИСКЛЮЧЕНИЯ 1,3 записей для "состояния заказа".

В этом случае

   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)  

Наконец, все, кто присоединился к заказам, будет иметь ОДИН ИД, и будет хорошо совпадать с таблицей заказов только по идентификатору заказа и получит желаемые результаты..

1 голос
/ 16 мая 2011

Другое возможное решение:

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
0 голосов
/ 17 мая 2011

Я использую «ответить на мой вопрос», потому что мне нужно опубликовать результаты ваших запросов.Итак.

К сожалению, не все ваши ответы работают.Давайте подготовим тестовую среду:

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;

Теперь давайте выберем последнее / максимальное состояние для каждого ордера, поэтому давайте запустим простой запрос:

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

это даст нам ПРЕВОСХОДНЫЕ результаты, без ракетостроенияпрямо сейчас:

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

Теперь для простоты, чтобы изменить наши запросы, чтобы получить Заказы , где Последнее состояние не равно 3 .

Мы ожидаем получить один результат строки с id_order = 3 .

Итак, давайте проверим наши запросы:

QUERY 1 от 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

Результат:

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

Так что не соответствует действительности

QUERY 2 от Тома Х. :

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

Результат:

id_order
--------
1
2

Так что не соответствует действительности

Любые предложения приветствуются.

РЕДАКТИРОВАТЬ

Благодаря комментарию Андрея М. у нас есть правильное решение .Это модификация запроса 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.date_add > OH1.date_add 
WHERE OH1.id_order_state NOT IN (3) AND OH2.id_order IS NULL

РЕДАКТИРОВАТЬ 2:

QUERY 3 от 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

Результат:

id_order
--------
3

Итак, наконец-то true

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...