查询以查找 "out of sequence" 行
Query to find "out of sequence" rows
我的 table 看起来类似于以下内容:
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'
本质上,这个 table 跟踪 ID_1 和 ID_2 所属的特定项目的状态变化。 ID_1 可能有很多行是ID,但它连接到同一个主要对象。 ID_2 也可能有很多行适用。
因此,要正确匹配两行,您应该检查 ID_1 和 ID_2 是否相同。我遇到的问题是由于一些设计不良的软件我们无法调整或摆脱(无论出于何种原因)。
状态更新通常没有任何特定顺序,但例如在这种情况下,特定 ID_1 + ID_2 对的状态为“一”后应为状态“二” .有些用户跳过了这一步,所以我想看看谁在跳过它。理想情况下,我希望此查询如何工作:
- 对于当天,我想查看按时间顺序跟随状态更新 'ONE' 的行,仅当它的状态不是 'TWO'。
- 每个 ID_1 + ID_2 我不需要超过一个实例,除非执行不良状态的用户不同。
- 这意味着如果 USER_1 在 ID_1 相同但 ID_2 不同的五个条目上违反,我只想要 1。如果 USER_1 和 USER_2 都违反了 ID_1,他们每个都需要一个条目。
- 但是,如果用户 1 在两个不同的 ID_1 上违规,则这两个都需要记录。
- 两个状态更新之前不能有除一个之外的任何内容,这种情况不需要考虑。
在上面的示例中,我想要以下行:
ID_1 | ID_2 | STATUS | STATUS_TIME | STATUS_BY
------------------------------------------------
1111 | 2222 | 'THREE' | [timestamp] | 'USER_3'
我非常希望我说得足够清楚,如果我遗漏了什么,请发表评论。这是在 IBM 的 DB2 版本 9.7 Fix Pack 7 上。我当前的 'solution' 冗长且无法正常运行,因为它列出了 ID_1 + ID_2 上使用 ONE 的所有用户,即使他们中的一些人使用了两个,而另一些人则没有。任何指导或帮助都很棒。
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"
您可以使用分析函数 LAG()
(或 LEAD()
)查找乱序记录。
根据实际数据,这两种方法中的任何一种都应该有效。
此查询 returns 前面没有 'TWO' 的 'THREE' 条记录:
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'
备选 returns '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'
如果您需要在前一行(或下一行之后)的行中查找值,请指定偏移量:LAG(status, 2)
(或LEAD(status, 2)
)。
我的 table 看起来类似于以下内容:
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'
本质上,这个 table 跟踪 ID_1 和 ID_2 所属的特定项目的状态变化。 ID_1 可能有很多行是ID,但它连接到同一个主要对象。 ID_2 也可能有很多行适用。
因此,要正确匹配两行,您应该检查 ID_1 和 ID_2 是否相同。我遇到的问题是由于一些设计不良的软件我们无法调整或摆脱(无论出于何种原因)。
状态更新通常没有任何特定顺序,但例如在这种情况下,特定 ID_1 + ID_2 对的状态为“一”后应为状态“二” .有些用户跳过了这一步,所以我想看看谁在跳过它。理想情况下,我希望此查询如何工作:
- 对于当天,我想查看按时间顺序跟随状态更新 'ONE' 的行,仅当它的状态不是 'TWO'。
- 每个 ID_1 + ID_2 我不需要超过一个实例,除非执行不良状态的用户不同。
- 这意味着如果 USER_1 在 ID_1 相同但 ID_2 不同的五个条目上违反,我只想要 1。如果 USER_1 和 USER_2 都违反了 ID_1,他们每个都需要一个条目。
- 但是,如果用户 1 在两个不同的 ID_1 上违规,则这两个都需要记录。
- 两个状态更新之前不能有除一个之外的任何内容,这种情况不需要考虑。
在上面的示例中,我想要以下行:
ID_1 | ID_2 | STATUS | STATUS_TIME | STATUS_BY
------------------------------------------------
1111 | 2222 | 'THREE' | [timestamp] | 'USER_3'
我非常希望我说得足够清楚,如果我遗漏了什么,请发表评论。这是在 IBM 的 DB2 版本 9.7 Fix Pack 7 上。我当前的 'solution' 冗长且无法正常运行,因为它列出了 ID_1 + ID_2 上使用 ONE 的所有用户,即使他们中的一些人使用了两个,而另一些人则没有。任何指导或帮助都很棒。
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"
您可以使用分析函数 LAG()
(或 LEAD()
)查找乱序记录。
根据实际数据,这两种方法中的任何一种都应该有效。
此查询 returns 前面没有 'TWO' 的 'THREE' 条记录:
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'
备选 returns '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'
如果您需要在前一行(或下一行之后)的行中查找值,请指定偏移量:LAG(status, 2)
(或LEAD(status, 2)
)。