是否可以按顺序查找(在有序的 table 中)多行?

Is it possible to find (in an ordered table) multiple rows in sequence?

如果我有一个按 ID 排序的 table,如下所示:

|---------------------|------------------|
|          ID         |        Key       |
|---------------------|------------------|
|          1          |        Foo       |
|---------------------|------------------|
|          2          |        Bar       |
|---------------------|------------------|
|          3          |        Test      |
|---------------------|------------------|
|          4          |        Test      |
|---------------------|------------------|

有没有办法检测出顺序匹配 where 子句的两行?

例如,在上面的table中,我想看看连续的两行是否有'test'的Key。

这在 SQL 中可行吗?

您可以使用 LEAD() window 函数,如:

with 
x as (
  select
    id, [key], 
    lead(id) over(order by id) as next_id,
    lead([key]) over(order by id) as next_key
  from my_table
)
select id, next_id from x where [key] = 'test' and next_key = 'test'

另一种选择是 Gaps-and-Islands 的变体

例子

Declare @YourTable Table ([ID] int,[Key] varchar(50))
Insert Into @YourTable Values 
 (1,'Foo')
,(2,'Bar')
,(3,'Test')
,(4,'Test')

Select ID_R1 = min(ID)
      ,ID_R2 = max(ID)
      ,[Key]
 From  (
        Select *
              ,Grp = ID-Row_Number() over(Partition By [Key] Order by ID) 
         From @YourTable
       ) A 
 Group By [Key],Grp
 Having count(*)>1

Returns

ID_R1   ID_R2   Key
3       4       Test

EDIT - Just in case the IDs are NOT Sequential

Select ID_R1 = min(ID)
      ,ID_R2 = max(ID)
      ,[Key]
 From  (
        Select *
              ,Grp = Row_Number() over(Order by ID)
                    -Row_Number() over(Partition By [Key] Order by ID) 
         From @YourTable
       ) A 
 Group By [key],Grp
 Having count(*)>1

你可以尝试使用ROW_NUMBERwindow函数检查间隙

SELECT [Key]
FROM (
     SELECT *,ROW_NUMBER() OVER(ORDER BY ID) -
           ROW_NUMBER() OVER(PARTITION BY [Key] ORDER BY ID) grp
     FROM T 
)t1
GROUP BY [Key]
HAVING COUNT(grp) = 2

您可以像

那样进行自连接
CREATE TABLE T(
  ID INT,
  [Key] VARCHAR(45)
);


INSERT INTO T VALUES
(1, 'Foo'),
(2, 'Bar'),
(3, 'Test'),
(4, 'Test');

SELECT MIN(T1.ID) One,
       MAX(T2.ID) Two,
       T1.[Key] OnKey
FROM T T1 JOIN T T2
ON T1.[Key] = T2.[Key]
   AND
   T1.ID <> T2.ID
GROUP BY T1.[Key];

CROSS JOIN

SELECT MIN(T1.ID) One,
       MAX(T2.ID) Two,
       T1.[Key] OnKey
FROM T T1 CROSS JOIN T T2
WHERE T1.[Key] = T2.[Key]
      AND
      T1.ID <> T2.ID
GROUP BY T1.[Key]

Demo