How can I check a group of numbers are consecutive in T-SQL?

前端 未结 3 1964
面向向阳花
面向向阳花 2020-12-30 14:49

If i was to have a table with an integer column containing n number of rows and wanted to check if they were consecutive, how could I do this?

DECLA         


        
相关标签:
3条回答
  • 2020-12-30 15:27

    Solution 1: (I have assumed the next value is current value plus 1; also I have added a PK):

    DECLARE @Temp TABLE 
    (
        IntegerValue INT PRIMARY KEY,
        Processed BIT
    );
    
    INSERT  @Temp(IntegerValue)
    SELECT  1
    UNION ALL
    SELECT  2
    UNION ALL
    SELECT  3
    UNION ALL
    SELECT  4
    UNION ALL
    SELECT  5;
    
    --Test 1
    DECLARE @RowCount INT;
    SELECT  @RowCount=COUNT(*)
    FROM    @Temp a
    LEFT JOIN @Temp b ON a.IntegerValue+1=b.IntegerValue
    WHERE   b.IntegerValue IS NOT NULL
    OR      b.IntegerValue IS NULL
    AND     a.IntegerValue = (SELECT MAX(IntegerValue) FROM @Temp);
    
    IF @RowCount = (SELECT COUNT(*) FROM @Temp)
        SELECT 'CONSECUTIVE' Test1_Result
    ELSE
        SELECT 'not CONSECUTIVE' Test1_Result;
    
    --Test 2
    DELETE @Temp;
    INSERT  @Temp(IntegerValue)
    SELECT  1
    UNION ALL
    SELECT  2
    UNION ALL
    SELECT  3
    UNION ALL
    SELECT  400
    UNION ALL
    SELECT  5;
    
    SELECT  @RowCount=COUNT(*)
    FROM    @Temp a
    LEFT JOIN @Temp b ON a.IntegerValue+1=b.IntegerValue
    WHERE   b.IntegerValue IS NOT NULL
    OR      b.IntegerValue IS NULL
    AND     a.IntegerValue = (SELECT MAX(IntegerValue) FROM @Temp);
    
    IF @RowCount = (SELECT COUNT(*) FROM @Temp)
        SELECT 'CONSECUTIVE' Test2_Result
    ELSE
        SELECT 'not CONSECUTIVE' Test2_Result;
    

    Solution 2: (less logical reads; the minimum IntegerValue must be 1)

    DECLARE @Temp TABLE 
    (
        IntegerValue INT PRIMARY KEY,
        Processed BIT
    );
    
    INSERT  @Temp(IntegerValue)
    SELECT  v.number
    FROM    master.dbo.spt_values v
    WHERE   v.type = 'P'
    AND     v.number > 0;
    
    SELECT CASE WHEN 
        (
            SELECT  TOP 1 q.IntegerValue
            FROM
            (
                SELECT  a.IntegerValue
                        ,ROW_NUMBER() OVER(ORDER BY a.IntegerValue) Num
                FROM    @Temp a
            ) q
            WHERE   q.IntegerValue <> q.Num
        ) IS NULL THEN 'Y' ELSE 'N' END
    

    Solution 3: ("quirky select" method; less logical reads, lower elapsed time)

    DECLARE @Temp TABLE 
    (
        IntegerValue INT PRIMARY KEY,
        Processed BIT
    );
    
    INSERT  @Temp(IntegerValue)
    SELECT  1
    UNION ALL
    SELECT  2
    UNION ALL
    SELECT  3
    UNION ALL
    SELECT  4
    UNION ALL
    SELECT  5;
    
    DECLARE @IsConsecutive BIT,
        @PreviousIntegerValue INT;
    
    SELECT  @IsConsecutive = 1;
    
    SELECT   @IsConsecutive = CASE WHEN @PreviousIntegerValue + 1 <> a.IntegerValue /*AND a.IntegerValue IS NOT NULL = condition necessary if IntegerValue field allows NULLs */ THEN 0 ELSE @IsConsecutive END
            ,@PreviousIntegerValue = a.IntegerValue
    FROM    @Temp a
    ORDER BY a.IntegerValue ASC
    OPTION (MAXDOP 1);
    
    SELECT  @IsConsecutive [IsConsecutive];
    
    0 讨论(0)
  • 2020-12-30 15:34
    SELECT CASE
             WHEN COUNT(DISTINCT IntegerValue) /*Or COUNT(*) dependant on how
                                                duplicates should be treated */ 
                    =  1 + MAX(IntegerValue) - MIN(IntegerValue) THEN 'Y'
             ELSE 'N'
           END
    FROM   @Temp  
    

    If you want to know where the gaps are you can use

    ;WITH T AS
    (
    SELECT *,
           DENSE_RANK() OVER (ORDER BY IntegerValue) - IntegerValue AS Grp
    FROM @Temp
    )
    SELECT MIN(IntegerValue) AS RangeStart, 
           MAX(IntegerValue) AS RangeEnd
    FROM T
    GROUP BY Grp
    ORDER BY MIN(IntegerValue)
    
    0 讨论(0)
  • 2020-12-30 15:41
    CREATE TABLE #T(ID INT)
    DECLARE @i INT
    SET @I = 1
    WHILE(@I <= LEN('12235588966'))
    BEGIN
      IF(SUBSTRING('12235588966',@i,1) = SUBSTRING('12235588966',@i-1,1))
      BEGIN
            INSERT INTO #T SELECT SUBSTRING('12235588966',@i,1)
      END
      SET @i = @I +1
    END
    
    SELECT * FROM #T
    
    0 讨论(0)
提交回复
热议问题