我有一个表格,用于保存订单的状态更改:
ORDER_ID | CHANGE_DATE | CODE_1 | CODE_2 | CODE_3
=============================================================
1 | 2012-09-01 12:20 | Z1 | NULL | NULL
1 | 2012-09-01 12:21 | Z2 | S01 | NULL
1 | 2012-09-01 12:22 | Z2 | S04 | NULL
2 | 2012-09-01 12:22 | Z1 | S01 | NULL
3 | 2012-09-01 12:23 | Z1 | S03 | NULL
1 | 2012-09-01 12:24 | Z1 | S02 | NULL
2 | 2012-09-01 12:29 | Z1 | S05 | NULL
1 | 2012-09-01 13:29 | Z5 | T01 | X01
2 | 2012-09-01 13:31 | Z1 | T01 | NULL
我需要为历史CODE_2 IN(S01,S02,S03)中的每个订单选择ORDER_ID,但在它们之后没有S04和S05。
在此特定情况下,查询应返回订单1,因为在CODE_2之后没有S04和S05,请注意订单1在历史记录中有S04,但之后它具有代码S02。 由于代码S03,它也应该返回订单3。 不应该返回订单2,因为他的历史记录中的最后一个代码是S05(最后来自S组)。
我可以在不加入其他桌子的情况下这样做吗?我想只从这个表中选择ORDER_ID。
答案 0 :(得分:1)
如果CHANGE_DATE
实际上是允许对行进行排序的列,那么以下内容就足够了:
declare @T table (ORDER_ID int,CHANGE_DATE datetime,CODE_1 char(2),CODE_2 char(3),CODE_3 char(3))
insert into @T(ORDER_ID,CHANGE_DATE,CODE_1,CODE_2,CODE_3) values
(1,'2012-09-01T12:20:00','Z1',NULL,NULL),
(1,'2012-09-01T12:21:00','Z2','S01',NULL),
(1,'2012-09-01T12:22:00','Z2','S04',NULL),
(2,'2012-09-01T12:20:00','Z1','S01',NULL),
(3,'2012-09-01T12:21:00','Z1','S03',NULL),
(1,'2012-09-01T12:24:00','Z1','S02',NULL),
(2,'2012-09-01T12:29:00','Z1','S05',NULL),
(1,'2012-09-01T13:23:00','Z5','T01','X01'),
(2,'2012-09-01T13:31:00','Z1','T01',NULL)
select distinct ORDER_ID from @T t where CODE_2 in ('S01','S02','S03')
and not exists(
select * from @T t2 where
t.ORDER_ID = t2.ORDER_ID and
t2.CODE_2 in ('S04','S05') and
t2.CHANGE_DATE > t.CHANGE_DATE
)