我的表类似于以下内容:
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。有些用户跳过这一步,所以我想知道谁在跳过它。理想情况下,我希望此查询能够起作用:
在上面的例子中,我想要以下一行:
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。任何指导或帮助都很棒。
答案 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”