MS SQL 不循环设置组 ID

MS SQL Set Group ID Without Looping

我想在 MS-SQL 中创建一个查询来创建一个包含递增组号的列。

这就是我希望我的数据的方式 return:

Column 1 | Column 2 | Column 3
------------------------------
    I    |     1    |     1
    O    |     2    |     2
    O    |     2    |     3
    I    |     3    |     4
    O    |     4    |     5
    O    |     4    |     6
    O    |     4    |     7
    O    |     4    |     8
    I    |     5    |     9
    O    |     6    |    10

那么我如何编写查询,以便 Column 2 每次 Column 1 变化时递增?

首先,要执行此类操作,您需要一些可以标识行顺序的列。如果你有一个确定这个顺序的列,例如一个标识列,它可以用来做这样的事情:

可运行示例:

CREATE TABLE #Groups
    (
      id INT IDENTITY(1, 1) , -- added identity to provide order
      Column1 VARCHAR(1)
    )

INSERT  INTO #Groups
        ( Column1 )
VALUES  ( 'I' ),
        ( 'O' ),
        ( 'O' ),
        ( 'I' ),
        ( 'O' ),
        ( 'O' ),
        ( 'O' ),
        ( 'O' ),
        ( 'I' ),
        ( 'O' );

;
WITH    cte
          AS ( SELECT   id ,
                        Column1 ,
                        1 AS Column2
               FROM     #Groups
               WHERE    id = 1
               UNION ALL
               SELECT   g.id ,
                        g.Column1 ,
                        CASE WHEN g.Column1 = cte.Column1 THEN cte.Column2
                             ELSE cte.Column2 + 1
                        END AS Column2
               FROM     #Groups g
                        INNER JOIN cte ON cte.id + 1 = g.id
             )
    SELECT  *
    FROM    cte
    OPTION (MAXRECURSION 0) -- required to allow for more than 100 recursions

DROP TABLE #Groups

此代码有效地遍历记录,将每一行与下一行进行比较,如果 Column1 中的值发生变化,则递增 Column2 的值。

如果您没有标识列,那么您可以考虑添加一个。

信用@AeroX:

对于 30K 条记录,最后一行:OPTION (MAXRECURSION 0) 需要在使用 Common Table Expression (CTE) 时覆盖默认的 100 次递归。设置为0,表示不受限制。

如果您有 sqlserver 2012+

,这将有效
DECLARE @t table(col1 char(1), col3 int identity(1,1))

INSERT @t values
('I'), ('O'), ('O'), ('I'), ('O'), ('O'), ('O'), ('O'), ('I'), ('O')

;WITH CTE AS
(
  SELECT 
    case when lag(col1) over (order by col3) = col1 
         then 0 else 1 end increase, 
    col1,
    col3
  FROM @t
)
SELECT
  col1,
  sum(increase) over (order by col3) col2,
  col3
FROM CTE

结果:

col1  col2  col3
I     1     1
O     2     2
O     2     3
I     3     4
O     4     5
O     4     6
O     4     7
O     4     8
I     5     9
O     6     10