Merging data in a single SQL table without a Cursor

后端 未结 4 1226
-上瘾入骨i
-上瘾入骨i 2021-01-31 19:51

I have a table with an ID column and another column with a number. One ID can have multiple numbers. For example

ID | Number
 1 |  25
 1 |  26
 1 |  30
 1 |  24
         


        
相关标签:
4条回答
  • 2021-01-31 20:39

    The key observation is that a sequence of numbers minus another sequence is a constant. We can generate another sequence using row_number. This identifies all the groups:

    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
    

    The rest is just aggregation.

    0 讨论(0)
  • I'd suggest using a WHILE loop structure with a table variable instead of the cursor.

    For example,

    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
    
    0 讨论(0)
  • 2021-01-31 20:49

    Solution with CTE and recursion:

    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
    

    Results at fiddlesql

    0 讨论(0)
  • 2021-01-31 20:51
    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;
    

    Live Example

    0 讨论(0)
提交回复
热议问题