从订单中选择最后的订单状态

时间:2011-05-16 17:57:43

标签: mysql sql

我有桌子:

订单:

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                 ...

如何获取所有order_id的那个订单的最后一个id_order_state(最后我的意思是MAX(id_history)或MAX(date_add))不等于1或3?

4 个答案:

答案 0 :(得分:4)

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 :(得分:1)

另一种可能的解决方案:

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

答案 2 :(得分:1)

我认为他所追求的是订单是完整的......即他们的最终状态,而不是那些专门排除1和3的人。无论状态代码如何,第一个预查询都应该是最大ID

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

只是为了重新显示你的数据......我已经为每个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)  

最后,加入订单的所有内容都会产生一个ID,并且仅与Order_ID上的订单表很好地匹配,并获得所需的结果。

答案 3 :(得分:0)

我正在使用&#34;回答我的问题&#34;因为我需要发布您的查询结果。如此。

不幸的是,并非你所有的答案都有效。让我们准备测试环境:

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 的一行结果。

因此,让我们测试一下我们的问题:

RedFilter 制作的QUERY 1:

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

所以不正确

由Tom H撰写的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

所以不正确

任何建议表示赞赏。

修改

感谢Andriy M.的评论,我们有正确的解决方案。它是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:

DRapp 制作的QUERY 3:

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

所以它终于真实