简体   繁体   English

按顺序排列的数字分组

[英]Group by numbers that are in sequence

I have some data like this:我有一些这样的数据:

row    id
1      1
2      36
3      37
4      38
5      50
6      51

I would like to query it to look like this:我想查询它看起来像这样:

 row    id    group
 1      1     1
 2      36    2
 3      37    2
 4      38    2
 5      50    3
 6      51    3

... so that I can GROUP BY where the numbers are consecutively sequential. ...这样我就可以按顺序排列数字。

Also, looping/cursoring is out of the question since I'm working with a pretty large set of data, thanks.此外,循环/游标是不可能的,因为我正在处理大量数据,谢谢。

with
  data(row, id) as (
    select * 
    from (
      values
       (1,1)
      ,(2,36)
      ,(3,37)
      ,(4,38)
      ,(5,50)
      ,(6,51)
    ) as foo(row, id)
  ),
  anchor(row, id) as (
    select row, id
    from data d1
    where not exists(select 0 from data d2 where d2.id = d1.id - 1)
  )
select d1.*, dense_rank() over(order by foo.id) as thegroup
from
  data d1
  cross apply (select max(id) from anchor where anchor.id <= d1.id) as foo(id)
order by
  d1.row
  ;
;WITH firstrows AS
(
    SELECT id, ROW_NUMBER() OVER (ORDER BY id) groupid
    FROM Table1 a
    WHERE id - 1 NOT IN (SELECT b.id FROM Table1 b)
)
SELECT id, 
    (
        SELECT MAX(b.groupid)
        FROM firstrows b
        WHERE b.id <= a.id
    ) groupid
FROM Table1 a

This solution does more work that is strictly necessary on the basis that there may be gaps in the sequence of row values, and on the assumption that those gaps should be ignored.这个解决方案做了更多的工作,这些工作是严格必要的,因为row值序列中可能存在间隙,并且假设这些间隙应该被忽略。

Set up test data:设置测试数据:

DECLARE @table TABLE
(ROW INT,
id INT
)

INSERT @table
SELECT 1,1
UNION SELECT 2,36
UNION SELECT 3,37
UNION SELECT 4,38
UNION SELECT 5,50
UNION SELECT 6,51

Output query Output查询

;WITH grpCTE
AS
(
    SELECT ROW, id,
    ROW_NUMBER() OVER (ORDER BY ROW
                        ) AS rn
    FROM @table
)
,recCTE
AS
(
    SELECT ROW, id, rn, 1 AS grp
    FROM grpCTE
    WHERE rn = 1

    UNION ALL

    SELECT g.row, g.id, g.rn, CASE WHEN g.id = r.id + 1 THEN r.grp ELSE r.grp + 1 END AS grp
    FROM grpCTE AS g
    JOIN recCTE AS r
    ON g.rn = r.rn + 1
)
SELECT row, id, grp FROM recCTE
create table #temp
(
    IDUnique int Identity(1,1),
    ID int, 
    grp int
)


Insert into #temp(ID) Values(1)
Insert into #temp(ID) Values(36)
Insert into #temp(ID) Values(37)
Insert into #temp(ID) Values(38)
Insert into #temp(ID) Values(50)
Insert into #temp(ID) Values(51)

declare @IDUnique int
declare @PreviousUnique int
declare @ID int
declare @grp int
declare @Previous int
declare @Row int

DECLARE @getAccountID CURSOR SET @getAccountID = CURSOR FOR SELECT Row_Number() Over(Order by IDUnique) Row, IDUnique, ID  From #temp
OPEN @getAccountID
FETCH NEXT FROM @getAccountID INTO @Row, @IDUnique, @ID 
WHILE @@FETCH_STATUS = 0
BEGIN
    IF(@Row = 1)
    Begin
        update #temp set grp = 1 Where IDUnique = @IDUnique
        set @Previous = @ID
        set @grp = 1
    End
    Else If (@Previous + 1 = @ID)
    Begin
        update #temp set grp = @grp Where IDUnique = @IDUnique
        set @Previous = @ID
    End
    Else
    Begin
        set @Previous = @ID
        set @grp = @grp + 1
        update #temp set grp = @grp Where IDUnique = @IDUnique
    End
    FETCH NEXT FROM @getAccountID INTO @Row, @IDUnique, @ID
END
CLOSE @getAccountID
DEALLOCATE @getAccountID

Select * from #temp
Drop Table #temp
 Select T.Id, T.Row, groupId as "Group", dr  FROM tbrows T
Left Outer Join
    (
    Select min(id) as groupId,DENSE_RANK() over( order by min(id)) as dr, MIN(row-id) as d, Sum(1) as s FROM tbrows
         Group BY (row-id)
    ) U
On (T.Id >= U.groupId) and (T.Id < U.groupId+U.s)
Order By T.Id

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM