MS SQL集组ID没有循环

时间:2015-03-25 10:02:33

标签: sql sql-server dense-rank

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

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

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 1IO表示In和Out。
  • Column 2是行组(在Column 1更改时应该增加)。
  • Column 3是行号。

那么如何编写查询以便Column 2每次Column 1更改时都会递增?

2 个答案:

答案 0 :(得分: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

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

如果您没有标识列,则可以考虑添加标识列。

来自@AeroX:

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

答案 1 :(得分:1)

如果您有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