【问题标题】:Is it possible to find (in an ordered table) multiple rows in sequence? [duplicate]是否可以按顺序找到(在有序表中)多行? [复制]
【发布时间】:2018-12-10 15:06:23
【问题描述】:

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

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

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

比如上表,我想看看有没有连续两行的Key是'test'。

这在 SQL 中可行吗?

【问题讨论】:

  • 您可以自行加入。
  • A SEQUENCE 是一个特定的服务器对象,不会影响这个问题。我删除了那个标签。

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


【解决方案1】:

另一种选择是 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

退货

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

【讨论】:

    【解决方案2】:

    您可以尝试使用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】:

      你可以做一个自我加入

      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

      【讨论】:

        【解决方案4】:

        可以使用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'
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-11-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-03
          • 2011-10-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多