根据特定值从 sql table 中检索行

Retrieve rows from sql table based on specific value

我创建了以下 table:

USE [myTestDB]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[test](
    [id] [numeric](19, 0) NOT NULL,
    [action] [nvarchar](255) NULL,
    [masterid] [numeric](19, 0) NULL
) ON [PRIMARY]
GO

table 上的数据:

id       action  masterid
1906035  001     514
1906057  002     514
1906064  002     514
1906956  003     514
1907007  002     514
1907010  004     514
1907097  002     514

所有行都具有相同的 masterid,我只想 return 行的操作值为 002,并且它们被放置在操作 001 之后和任何其他操作之前。

任何其他操作(例如 003、004)后值为 002 的行不得 returned。

我想达到的效果是这样的:

id       action  masterid
1906057  002     514
1906064  002     514

使用以下查询,returns 具有操作 002 的所有行:

select t.[id]
      ,t.[action]
      ,t.[masterid]
from [myTestDB].[dbo].[test] t
left join [myTestDB].[dbo].[test] t2 on (t2.masterid = t.masterid and t2.action = 001)
where t.action = 002
and t.id > t2.id
id       action   masterid
1906057  002      514
1906064  002      514  
1907007  002      514
1907097  002      514

如何排除在操作 003 和 004 之后出现的 ID 为 1907007 和 1907097 的行?

提前致谢!

我会把它作为一个缺口和孤岛问题来解决。首先,定义每次看到操作“001”时重置的记录组。然后,从每组开始统计非“002”记录的条数,最后过滤:

select id, action, masterid
from (
    select t.*, 
        sum(case when action in ('001', '002') then 0 else 1 end) over(partition by masterid, grp order by id) as flag
    from (
        select t.*, 
            sum(case when action = '001' then 1 else 0 end) over(partition by masterid order by id) as grp
        from test t
    ) t
) t
where action = '002' and flag = 0 and grp > 0

Demo on DB Fiddle:

     id | action | masterid
------: | :----- | -------:
1906057 | 002    |      514
1906064 | 002    |      514