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

前端 未结 3 1965
面向向阳花
面向向阳花 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];
    

提交回复
热议问题