Найти недостающие строки между 2 числами в SQL Server - PullRequest
0 голосов
/ 02 мая 2019

Я хочу найти все отсутствующие строки между 2 числами в SQL Server.

Например, у меня есть диапазон от 100,000 до 200,000 и столбец [INVOICE_NO] в таблице в SQL Server.Для каждого числа должна быть строка от 100,000 до 200,000.Как я могу проверить и найти пропущенные номера счетов в таблице?

Я понимаю, как это сделать, если каждое число между 100,000 и 200,000 было сохранено в отдельной таблице, тогда я мог бы просто сделать and not in (select ...)но не уверен, как это сделать без.

Ответы [ 2 ]

1 голос
/ 02 мая 2019

Как прокомментировано, я бы использовал здесь таблицу подсчета, а не rCTE:

DECLARE @Start int, @End int;
SET @Start = 100000;
SET @End = 200000;

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) I
    FROM N N1, N N2, N N3, N N4, N N5, N N6) --1M rows should be enough
SELECT T.I AS MISSING_INVOICE_NO
FROM Tally T
     --LEFT JOIN YourTable YT ON T.I = YT.INVOICE_NO
WHERE T.I BETWEEN @Start AND @End
--AND YT.INVOICE_NO IS NULL

Вам нужно закомментировать и настроить строки на JOIN для вашей таблицы.

В качестве доказательства рассуждений используйте следующие сценарии:

DECLARE @Start int, @End int;
SET @Start = 100000;
SET @End = 200000;

SET STATISTICS TIME ON;

PRINT N'Tally Table';

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) I
    FROM N N1, N N2, N N3, N N4, N N5, N N6) --1M rows should be enough
SELECT *
FROM Tally T
WHERE T.I BETWEEN @Start AND @End;

PRINT N'rCTe';

WITH rCTE AS(
    SELECT @Start AS I
    UNION ALL
    SELECT I + 1
    FROM rCTE r
    WHERE r.I + 1 <= @End)
SELECT *
FROM rCTE
OPTION (MAXRECURSION 0);

SET STATISTICS TIME OFF;

Время, необходимое для заполнения таблицы подсчета (в моем экземпляре Production):

CPU time = 78 ms,  elapsed time = 106 ms.
CPU time = 78 ms,  elapsed time = 95 ms.
CPU time = 62 ms,  elapsed time = 91 ms.
CPU time = 78 ms,  elapsed time = 105 ms.

Метод rCTE, однако, был таким:

CPU time = 2547 ms,  elapsed time = 3695 ms.
CPU time = 2250 ms,  elapsed time = 2500 ms.
CPU time = 1813 ms,  elapsed time = 1930 ms.
CPU time = 2750 ms,  elapsed time = 3220 ms.

Это большая разница во времени, так как решение по подсчету составляло в среднем около 100 мс,где значение rCTe составляло от 2 до 4 секунд.

0 голосов
/ 02 мая 2019

Если вы можете иметь дело с диапазонами, вы можете получить все пробелы с:

select (invoice_no + 1) as first_missing_invoice_no, 
       (next_invoice_no - 1) as last_missing_invoice_no,
       count(*) as num_missing
from (select i.*,
             lead(invoice_no) over (order by invoice_no) as next_invoice_no
      from invoices i
     ) i
where next_invoice_no <> invoice_no + 1;

Это может быть принято для определенного диапазона, если диапазоны соответствуют вашим потребностям.

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