【问题标题】:TSQL - GROUP BY on continous rows onlyT SQL - 仅对连续行进行 GROUP BY
【发布时间】:2021-11-20 07:57:23
【问题描述】:

我正在使用 SQL Server 2017 (v14.0)。

我有一张这样的桌子:

Key | State    | from       | until      |
----+----------+------------+------------+
100 | open     | 01.01.2021 | 01.01.2021 |
100 | open     | 02.01.2021 | 02.01.2021 |
100 | closed   | 03.01.2021 | 13.01.2021 |
100 | open     | 14.01.2021 | 20.01.2021 |
100 | open     | 20.01.2021 | 30.01.2021 |

我想按KeyState 对其进行分组,但仅限于连续行。

所以我的预期结果是这样的:

Key | State    | from       | until      |
----+----------+------------+------------+
100 | open     | 01.01.2021 | 02.01.2021 |
100 | closed   | 03.01.2021 | 13.01.2021 |
100 | open     | 14.01.2021 | 30.01.2021 |

知道如何做到这一点吗?我有强烈的感觉,这应该可以在ROW_NUMBER 的帮助下以某种方式实现,但我还无法弄清楚......

(在此示例中,可能会出现一些奇怪的 group by calendarweek 或类似的数据,但这不是我的意图)

【问题讨论】:

    标签: sql sql-server tsql group-by sql-server-2017


    【解决方案1】:

    这是一个差距和孤岛问题。一种解决方案是:

    WITH cte1 AS (
        SELECT *, CASE WHEN LAG([state]) OVER (PARTITION BY [key] ORDER BY [from]) = [state] THEN 0 ELSE 1 END AS chg
        FROM t
    ), cte2 AS (
        SELECT *, SUM(chg) OVER (PARTITION BY [key] ORDER BY [from]) AS grp
        FROM cte1
    )
    SELECT [key], grp, MIN([state]), MIN([from]), MAX([until])
    FROM cte2
    GROUP BY [key], grp
    ORDER BY [key], grp
    

    【讨论】:

      【解决方案2】:

      一种可能性如下添加:

      Create table myTable_o1
       (
       [key] int
       ,[state] varchar(100)
       ,[From] date
       ,[Until] date
       )
      
      insert into myTable_o1 values (100, 'open', '2021-01-01','2021-01-01')
      insert into myTable_o1 values (100, 'open', '2021-01-02','2021-01-02')
      insert into myTable_o1 values (100, 'closed', '2021-01-03','2021-01-13')
      insert into myTable_o1 values (100, 'open', '2021-01-4','2021-01-20')
      insert into myTable_o1 values (100, 'open', '2021-01-20','2021-01-30')
      
      SELECT 
         [key] 
         ,[state] 
         ,[From] 
         ,[until] 
      FROM
      (
      Select 
        [key] 
       , [state] 
       , [From] 
       , row_number() over (partition by tiles order by [key]) row_num
       , ISNULL(Lead(Until) over (partition by tiles order by [key]) , Until) [until]
       FROM
       (
          SELECT * ,
          Ntile(2) over ( order by [Key]) as [tiles]
          from myTable_o1
         ) AS A
       ) AS B WHERE B.row_num in (1,3)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-11
        • 1970-01-01
        • 1970-01-01
        • 2012-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多