查询以查找“无序”行

时间:2016-09-28 18:57:19

标签: sql db2 db2-luw

我的表类似于以下内容:

ID_1 | ID_2 | STATUS   | STATUS_TIME | STATUS_BY
------------------------------------------------
1111 | 2222 | 'ONE'    | [timestamp] | 'USER_1'
3333 | 4444 | 'ONE'    | [timestamp] | 'USER_2'
1111 | 2222 | 'THREE'  | [timestamp] | 'USER_3'
3333 | 4444 | 'TWO'    | [timestamp] | 'USER_2'
3333 | 4444 | 'THREE'  | [timestamp] | 'USER_4'

此表基本上跟踪ID_1和ID_2所属的特定项目的状态更改。 ID_1可能有很多行,它是ID,但它连接到同一个主对象。 ID_2也可能包含许多适用的行。

因此,要正确匹配两行,您应该检查ID_1和ID_2是否相同。我遇到的问题是由于一些设计不佳的软件我们无法调整或摆脱(无论出于何种原因)。

状态更新一般没有任何特定顺序,但是例如在这种情况下,特定ID_1 + ID_2对的状态为ONE后应该是状态TWO。有些用户跳过这一步,所以我想知道谁在跳过它。理想情况下,我希望此查询能够起作用:

  • 对于当天,我希望看到按时间顺序排在状态更新为“ONE”的行后面的行,仅当它的状态不是“TWO”时才会显示。
  • 每个ID_1 + ID_2我不需要多个实例,除非执行不良状态的用户不同。
  • 这意味着如果USER_1违反了ID_1相同但ID_2不同的五个条目,我只想要1.如果USER_1和USER_2都违反ID_1,则每个条目都需要一个条目。
  • 但是,如果USER 1违反了两个不同的ID_1,则两者都需要记录。
  • TWO的状态更新之前不能包含ONE,不需要考虑此情况。

在上面的例子中,我想要以下一行:

ID_1 | ID_2 | STATUS   | STATUS_TIME | STATUS_BY
------------------------------------------------
1111 | 2222 | 'THREE'  | [timestamp] | 'USER_3'

我非常希望自己足够清楚,如果我遗漏任何东西,请发表评论。这是在IBM的DB2版本9.7 Fix Pack 7上。我当前的“解决方案”是冗长的,并且无法正常运行,因为它列出了使用ONE的ID_1 + ID_2上的所有用户,即使其中一些使用了TWO,其中一些用户没有“T。任何指导或帮助都很棒。

2 个答案:

答案 0 :(得分:2)

您可以使用分析函数LAG()(或LEAD())来查找无序记录。

根据实际数据,这些方法中的任何一种都应该有效。

此查询返回“THREE”记录,前面没有“TWO”:

select * from (
 select 
   t.*, 
   lag(status) over (partition by id_1, id_2 order by status_time) as prev_status 
 from test t
) t1 where status = 'THREE' and prev_status != 'TWO'

替代方案会返回“ONE”记录,而不是“TWO”:

select * from (
 select 
  t.*, 
  lead(status) over (partition by id_1, id_2 order by status_time) as next_status 
 from test t
) t1 where status = 'ONE' and next_status != 'TWO'

如果您需要在前一行(或下一行)之前的行中查找值,请指定offset:LAG(status, 2)(或LEAD(status, 2))。

答案 1 :(得分:1)

SELECT distinct ID_1, Status_By from table t -- only one user by id_1
WHERE status !<>'ONE' -- is not the first row
AND not exists
(select 1 from table t0 where t0.id_1=t.id_1 and t0.id_2=t.id_2 and t0.status_time<t.status_time  and status <> 'ONE') -- is the  row that follows
and status <> 'TWO' -- and the status is not 'TWO'

这应该适用于您的条件1和2,不确定您的3条件是什么意思,因为您说它不需要考虑。如果第三个条件也需要测试,那么可以添加一个“union all”