简体   繁体   English

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

[英]Retrieve rows from sql table based on specific value

I have created the following 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

Data on 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

All rows have the same masterid, and I only want to return rows whose value of action is 002 and they are placed right after action 001, and before any other actions.所有行都有相同的 masterid,我只想返回 action 值为 002 的行,它们被放置在 action 001 之后,并且在任何其他操作之前。

Rows that have value 002 after any other action (eg 003, 004), must not be returned.在任何其他操作(例如 003、004)之后具有值 002 的行不得返回。

What I want to achieve, is this:我想要实现的是:

id       action  masterid
1906057  002     514
1906064  002     514

Using the following query, returns all rows with action 002:使用以下查询,返回具有操作 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

How can I exclude rows with IDs 1907007 & 1907097 that appear after actions 003 & 004?如何排除在操作 003 和 004 之后出现的 ID 为 1907007 和 1907097 的行?

Thank you in advance!先感谢您!

I would adress this as a gaps-and-islands problem.我会将其视为一个差距和岛屿问题。 First, define groups of records that reset everytime action "001" is seen.首先,定义每次看到操作“001”时重置的记录组。 Then, count the number of non-"002" records from the beginning of each group, and finally filter:然后,统计每组开始的非“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 : DB Fiddle 上的演示

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM