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

时间:2018-12-10 15:06:23

标签: sql sql-server tsql sql-order-by where

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

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

有没有一种方法可以检测到顺序匹配where子句的两行?

例如,在上表中,我想查看是否连续有两行的键为“ test”。

这在SQL中可行吗?

4 个答案:

答案 0 :(得分:2)

另一种选择是差距和岛屿变化

示例

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

返回

ID_R1   ID_R2   Key
3       4       Test
  

编辑-以防万一ID不连续

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

答案 1 :(得分:1)

您可以使用LEAD()窗口函数,如下所示:

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'

答案 2 :(得分:1)

您可以尝试使用ROW_NUMBER窗口功能检查间隙。

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

答案 3 :(得分:1)

您可以通过以下方式进行自我加入

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