Поиск отсутствующего порядкового номера в таблице SQL 2008 - PullRequest
0 голосов
/ 17 мая 2018

У меня есть таблица, которая возвращает запрос по этому запросу:

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') не равен 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 голосов
/ 17 мая 2018

Вы можете попробовать следующий запрос:

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;

Это тоже должно работать правильно. Но я лично предпочитаю свой исходный запрос, поскольку он основан на операциях над множествами, а не на циклах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...