Вы можете попробовать следующий запрос:
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;
Это тоже должно работать правильно. Но я лично предпочитаю свой исходный запрос, поскольку он основан на операциях над множествами, а не на циклах.