在SQL 2008表中查找缺少的序列号

时间:2018-05-17 06:44:36

标签: sql-server-2008

我有一个表格,通过此查询返回以下内容:

SELECT *    
  FROM [PROC_MN]    
  where PO_NO='GV17885' AND DOC_NO='622843' 

ID  PO_NO   DOC_NO  PROCESS_SEQ PROCESS_NAME    STATUS  TIME
756 GV17885 622843  2   R.M.Requisition Start   23-04-18 15:29
788 GV17885 622843  2   R.M.Requisition Finish  23-04-18 15:50
289 GV17885 622843  1   CTP Start   23-04-18 8:57
426 GV17885 622843  1   CTP Finish  23-04-18 10:09
901 GV17885 622843  3   Material Cut    Start   23-04-18 17:23
903 GV17885 622843  3   Material Cut    Finish  23-04-18 17:26
1669    GV17885 622843  4   Print   Start   24-04-18 13:59
1712    GV17885 622843  4   Print   Finish  24-04-18 14:44
3421    GV17885 622843  5   Q.C Start   27-04-18 8:04
3492    GV17885 622843  5   Q.C Finish  27-04-18 8:42
3630    GV17885 622843  7   RFID    Start   27-04-18 9:36
3632    GV17885 622843  7   RFID    Finish  27-04-18 9:38
4264    GV17885 622843  8   Q.C Start   27-04-18 14:58
4288    GV17885 622843  8   Q.C Finish  27-04-18 15:16
4729    GV17885 622843  9   Encode  Start   28-04-18 8:48
4734    GV17885 622843  9   Encode  Finish  28-04-18 8:49
4698    GV17885 622843  9   Encode  Start   28-04-18 8:24
4722    GV17885 622843  9   Encode  Finish  28-04-18 8:47
5016    GV17885 622843  10  Q.C Start   28-04-18 13:38
5073    GV17885 622843  10  Q.C Finish  28-04-18 14:11

我想找到缺少的PROCESS_SEQ行,上面的结果我们发现丢失的PROCESS_SEQ是6号。我使用以下查询,但它没有返回任何/。请帮忙!

SET NOCOUNT ON;

DECLARE @Min BIGINT
DECLARE @Max BIGINT
DECLARE @i BIGINT

如果OBJECT_ID(' tempdb ..#TempTable')IS NOT NULL         开始             DROP TABLE #TempTable         END

CREATE TABLE #TempTable
    (
      TempOrderNumber BIGINT
    )

SELECT  @Min = ( SELECT MIN([PROCESS_SEQ])
                 FROM   [PROC_MN] WITH ( NOLOCK )
                 WHERE PO_NO='GV17885' AND [DOC_NO]='622843')
SELECT  @Max = ( SELECT MAX([PROCESS_SEQ])
                 FROM   [PROC_MN] WITH ( NOLOCK )
                 WHERE PO_NO='GV17885' AND [DOC_NO]='622843')
SELECT  @i = @Min

WHILE @i <= @Max 
    BEGIN
        INSERT  INTO #TempTable
                SELECT  @i

        SELECT  @i = @i + 1

    END

SELECT  TempOrderNumber
FROM    #TempTable
        LEFT JOIN [PROC_MN] o WITH ( NOLOCK ) ON tempordernumber = o.[PROCESS_SEQ]
WHERE   o.[PROCESS_SEQ] IS NULL 

1 个答案:

答案 0 :(得分:0)

您可以尝试以下查询:

WITH
    [MISSING_RANGES] AS
    (
        SELECT
            [MISSING_RANGE_NO] = ROW_NUMBER() OVER (ORDER BY P.[PO_NO], P.[DOC_NO], P.[PROCESS_SEQ]),
            P.[PO_NO],
            P.[DOC_NO],
            [FIRST_MISSING] = P.[PROCESS_SEQ] + 1,
            [LAST_MISSING] = N.[PROCESS_SEQ] - 1
        FROM
            [PROC_MN] AS P
            OUTER APPLY (SELECT [PROCESS_SEQ] = MIN([PROCESS_SEQ])
                         FROM [PROC_MN]
                         WHERE
                             [PO_NO] = P.[PO_NO] AND
                             [DOC_NO] = P.[DOC_NO] AND
                             [PROCESS_SEQ] > P.[PROCESS_SEQ]) AS N
        WHERE
            N.[PROCESS_SEQ] > P.[PROCESS_SEQ] + 1
    ),
    [MISSING_SEQUENCES] AS
    (
        SELECT
            [MISSING_RANGE_NO],
            [MISSING_PROCESS_SEQ] = [FIRST_MISSING]
        FROM
            [MISSING_RANGES]
    UNION ALL
        SELECT
            R.[MISSING_RANGE_NO],
            S.[MISSING_PROCESS_SEQ] + 1
        FROM
            [MISSING_RANGES] AS R
            INNER JOIN [MISSING_SEQUENCES] AS S ON S.[MISSING_RANGE_NO] = R.[MISSING_RANGE_NO]
        WHERE
            S.[MISSING_PROCESS_SEQ] < R.[LAST_MISSING]
    )
SELECT DISTINCT
    R.[PO_NO],
    R.[DOC_NO],
    S.[MISSING_PROCESS_SEQ]
FROM
    [MISSING_RANGES] AS R
    INNER JOIN [MISSING_SEQUENCES] AS S ON S.[MISSING_RANGE_NO] = R.[MISSING_RANGE_NO]
--WHERE
--    R.[PO_NO] = ? AND
--    R.[DOC_NO] = ?
ORDER BY
    R.[PO_NO],
    R.[DOC_NO],
    S.[MISSING_PROCESS_SEQ]
OPTION (MAXRECURSION 10000);

(为了测试目的,我把WHERE子句用于过滤评论中的特定[PO_NO]和[DOC_NO]值。)

编辑(响应其他更新的帖子):

这是我个人版的SQL脚本。与您的一样,它会生成一个包含序列的临时表(从最小到最大),并选择无法连接数据表中记录的所有值:

DECLARE @PO_NO VARCHAR(10) = 'GV17885';
DECLARE @DOC_NO VARCHAR(10) = '622843';

DECLARE @TempTable TABLE
(
    [TempOrderNumber] BIGINT PRIMARY KEY
);

DECLARE @Min BIGINT;
DECLARE @Max BIGINT;

SELECT
    @Min = MIN([PROCESS_SEQ]),
    @Max = MAX([PROCESS_SEQ])
FROM
    [PROC_MN] WITH (NOLOCK)
WHERE
    [PO_NO] = @PO_NO AND
    [DOC_NO] = @DOC_NO;

DECLARE @i BIGINT = @Min;

WHILE (@i <= @Max) BEGIN
    INSERT INTO @TempTable ([TempOrderNumber])
    SELECT @i;

    SET @i += 1;
END;

SELECT
    [TempOrderNumber]
FROM
    @TempTable
    LEFT JOIN [PROC_MN] AS O WITH (NOLOCK) ON
        [TempOrderNumber] = O.[PROCESS_SEQ]
        AND O.[PO_NO] = @PO_NO
        AND O.[DOC_NO] = @DOC_NO
WHERE
    O.[PROCESS_SEQ] IS NULL;

这也应该正常工作。但我个人更喜欢我的原始查询,因为它基于集合操作而不是循环。