在单个SQL表中合并数据而不使用游标

在单个SQL表中合并数据而不使用游标,sql,sql-server-2008,tsql,cursor,aggregate,Sql,Sql Server 2008,Tsql,Cursor,Aggregate,我有一个带有ID列的表和另一个带有数字的列。一个ID可以有多个号码。比如说 ID | Number 1 | 25 1 | 26 1 | 30 1 | 24 2 | 4 2 | 8 2 | 5 现在根据这些数据,在一个新的表中,我想要这个 ID | Low | High 1 | 24 | 26 1 | 30 | 30 2 | 4 | 5 2 | 8 | 8 如您所见,我希望合并任何数字连续的数据,如24、25、26。所以现在低点是24,

我有一个带有ID列的表和另一个带有数字的列。一个ID可以有多个号码。比如说

ID | Number
 1 |  25
 1 |  26
 1 |  30
 1 |  24
 2 |  4
 2 |  8
 2 |  5
现在根据这些数据,在一个新的表中,我想要这个

ID | Low | High 
1  |  24 |  26
1  |  30 |  30
2  |  4  |  5
2  |  8  |  8
如您所见,我希望合并任何数字连续的数据,如24、25、26。所以现在低点是24,高点是26,然后30仍然是一个单独的范围。我处理的是大量数据,因此出于性能考虑,我宁愿不使用光标(这是我以前所做的,并且会让事情慢很多)…实现这一点的最佳方法是什么?我不是SQL专业人士,所以我不确定是否有一个函数可以使这变得更容易,或者实现这一点的最快方法是什么


谢谢你的帮助。

关键的观察结果是一个数字序列减去另一个序列是一个常数。我们可以使用
行号
生成另一个序列。这标识了所有组:

select id, MIN(number) as low, MAX(number) as high
from (select t.*,
             (number - ROW_NUMBER() over (partition by id order by number) ) as groupnum
      from t
     ) t
group by id, groupnum

剩下的只是聚合。

我建议使用
WHILE
循环结构和表变量来代替光标

比如说,

DECLARE @TableVariable TABLE
(
    MyID int IDENTITY (1, 1) PRIMARY KEY NOT NULL,
    [ID] int,
    [Number] int
)

DECLARE @Count int, @Max int

INSERT INTO @TableVariable (ID, Number)
SELECT ID, Number
FROM YourSourceTable

SELECT @Count = 1, @Max = MAX(MyID)
FROM @TableVariable

WHILE @Count <= @Max
BEGIN

    ...do your processing here...


    SET @Count = @Count + 1

END
DECLARE@TableVariable表
(
MyID int IDENTITY(1,1)主键不为空,
[ID]int,
[数字]整数
)
声明@Count int,@Max int
插入@TableVariable(ID,编号)
选择身份证号码
从您的SourceTable
选择@Count=1、@Max=Max(MyID)
来自@TableVariable

而@Count使用CTE和递归的解决方案:

WITH CTE AS (
  SELECT T.ID, T.NUMBER, T.NUMBER AS GRP
  FROM T 
  LEFT OUTER JOIN T T2 ON T.ID = T2.ID AND T.NUMBER -1 = T2.NUMBER 
  WHERE T2.ID IS NULL
  UNION  ALL
  SELECT T.ID, T.NUMBER, GRP
  FROM CTE 
  INNER JOIN T
  ON T.ID = CTE.ID AND T.NUMBER  = CTE.NUMBER + 1
)
SELECT ID, MAX( NUMBER ), MIN(NUMBER)
FROM CTE
GROUP BY ID, GRP


您使用的是什么rdbms?对不起,我在问题中添加了另一个标签。这是SQL Server 2008。几乎一样:。什么?不SQL中的循环几乎总是错误的。SQL在设计时考虑到了集合逻辑,当编写实现以利用这一点时,通常性能最佳。我也有一种感觉,这种
,而
循环将使用一些与游标相同的底层进程,这将使您处于与以前一样糟糕的境地。除此之外,您还没有显示重置
@Count
..的必要条件。在许多情况下,与表变量结合使用,性能提升是值得的
@Count
在这种情况下不需要重置,只需在处理表变量中的每个记录时递增,尽管这可能会根据OP的要求而改变。
CREATE TABLE Table1
    ([ID] int, [Number] int)
;

INSERT INTO Table1
    ([ID], [Number])
VALUES
    (1, 25),
    (1, 26),
    (1, 30),
    (1, 24),
    (2, 4),
    (2, 8),
    (2, 5)
;

    select ID, 
           MIN(Number)
         ,(SELECT MIN(Number) 
                  FROM (SELECT TOP 2 Number from Table1 WHERE ID =
                  T1.Id ORDER BY Number DESC) as DT)
    from Table1 as T1
    GROUP BY ID
    UNION 
    SELECT ID, MAX(Number), MAX(Number)
    FROM Table1 as T1
    GROUP BY ID;