Как найти пропущенное число в таблице

В одной из таблиц сохраняются заранее сгенерированные серийные номера (последовательности).
При сохранении этих серийных номеров, некоторые из них могут быть «потеряны», т.е образуются пропуски. Моя задача, найти эти пропуски в сохранённых серийных номерах.

Например, в таблице последовательность чисел: (7001, 7002, 7004, 7005, 7006, 7010).
В этой последовательности, с 7001 до 7010, отсутствуют (7003, 7007, 7008, 7009).

Есть ли в БД какая-то встроенная функция, которая найдёт эти пропуски чисел? Если нет, то какой алгоритм решения задачи?


Свободный перевод How to check any missing number from a series of numbers? от участника @Samcoder

Stanislav Volodarskiy's user avatar

задан 14 июл 2020 в 16:25

0xdb's user avatar

1

Попробуйте так:

SELECT t1.n+1 as "From", MIN(t2.n)-1 as "To"
FROM testdata t1
JOIN testdata t2 ON t1.n < t2.n
GROUP BY t1.n
HAVING t1.n+1 < MIN(t2.n)
/

Результат для последовательности как в вопросе:

      From         To
---------- ----------
      7003       7003
      7007       7009

Свободный перевод ответа от участника @Patrick

ответ дан 14 июл 2020 в 16:39

0xdb's user avatar

0xdb0xdb

51.4k194 золотых знака56 серебряных знаков232 бронзовых знака

Решение, если граничные значения последовательности неизвестны:

with testdata as (
    select column_value n 
    from sys.odciNumberList (7001, 7002, 7004, 7005, 7006, 7010)
)
select nmin-1+level missing 
from ( 
    select min (n) nmin, max (n) nmax
    from testdata 
) connect by level <= nmax-nmin+1
minus
select n from testdata
/

   MISSING
----------
      7003
      7007
      7008
      7009

Свободный перевод ответа от участника @Rob van Wijk

ответ дан 14 июл 2020 в 16:25

0xdb's user avatar

0xdb0xdb

51.4k194 золотых знака56 серебряных знаков232 бронзовых знака

Учитывая, что заполнение коллекций почти всегда упорядочено, то есть, в первом элементе минимальное значение, а в последнем — максимальное, то на чистом PL/SQL решается так:

var rc refcursor
declare 
    nt1 numtab := numtab (7001, 7002, 7004, 7005, 7006, 7010);
    nt2 numtab := numtab ();
    res numtab;
begin
    nt2.extend (nt1(nt1.last) - nt1(nt1.first) + 1); 
    for ix in 1 .. nt1(nt1.last) - nt1(nt1.first) + 1 loop 
        nt2 (ix) := nt1 (nt1.first) + ix -1; end loop; 
    res := nt2 multiset except nt1;    
    open :rc for select column_value missing from table (res);
end; 
/

   MISSING
----------
      7003
      7007
      7008
      7009

ответ дан 14 июл 2020 в 20:32

0xdb's user avatar

0xdb0xdb

51.4k194 золотых знака56 серебряных знаков232 бронзовых знака

Допустим, эти числа, обозначающие порядковые номера, расположены в столбце А, например, в ячейках с А6 по А135. Тогда вы в каком либо столбце, например в столбце F, начиная с 7 строки, т.е. в ячейке F7 пишете такую формулу: ЕСЛИ(A7-A6>1;»*»;»»)­.

В формуле обозначения ячеек записываются латинскими буквами. Теперь выделяете ячейку F7, подводите курсор к правому нижнему углу ячейки (там черный квадратик). Тогда курсор из обычного вида перейдёт в вид прямой чёрный крестик (+). Теперь, нажимаете левую клавишу мыши и удерживая её нажатой, протягиваете курсор по всему столбцу F, включая ячейку F135, и после этого отпускаете клавишу мышки. Тем самым Вы скопируете формулу на весь столбец F, точнее на диапазон ячеек F7-F135. В тех строках, в которых разность между значениями в текущей и вышестоящей строке больше 1, появятся звёздочки (*).

Предположим, у вас есть длинный список порядковых номеров для маркировки элементов, таких как номера чеков в банковских выписках, обычно мы прокручиваем и находим недостающие порядковые номера вручную. Иногда это довольно сложно и требует много времени. Вы можете придумать хитрые способы справиться с этим. Да, есть несколько простых способов быстро и удобно определить и найти последовательность отсутствующих чисел в Excel 2007, Excel 2010 и Excel 2013.

Определите последовательность отсутствующих чисел с помощью формулы ЕСЛИ

Определите последовательность отсутствующих чисел с помощью формулы массива

Определите последовательность пропущенных чисел с помощью Kutools for Excel быстро


стрелка синий правый пузырь Определите последовательность отсутствующих чисел с помощью формулы ЕСЛИ

Как мы все знаем, большинство порядковых номеров имеют фиксированное приращение 1, например, 1, 2, 3,…, N. Следовательно, если вы можете определить, что число не меньше 1, чем его следующее число, это означает, что число отсутствует. .

Мы покажем вам руководства с примером, как показано на следующем скриншоте:

док определить недостающие числа 1

1. В пустой ячейке введите формулу = ЕСЛИ (A3-A2 = 1; «»; «Отсутствует»), и нажмите Enter ключ. В этом случае мы вводим формулу в ячейку B2.

док-идентификация-отсутствующие-номера2

Если нет пропущенных чисел, эта формула ничего не вернет; если пропущенные числа существуют, он вернет текст «Отсутствует» в активной ячейке.

2. Выберите ячейку B2 и перетащите маркер заполнения над диапазоном ячеек, который вы хотите содержать эту формулу. Теперь он идентифицирует отсутствующие числа с текстом «Отсутствует» в соответствующих ячейках столбца B. См. Следующий снимок экрана:

док-идентификация-отсутствующие-номера3


стрелка синий правый пузырь Определите последовательность отсутствующих чисел с помощью формулы массива

Иногда требуется не только определить последовательность отсутствующих номеров, но и перечислить отсутствующие номера. Вы можете справиться с этим, выполнив следующие шаги:

1. в соседней ячейке введите формулу = SMALL(IF(ISNA(MATCH(ROW(A$1:A$30),A$1:A$30,0)),ROW(A$1:A$30)),ROW(A1))

A1: A30 = диапазон чисел, последовательность для проверки от 1 до 30

2. нажмите Shift + Ctrl + Enter Ключи вместе, чтобы закончить формулу. Скопируйте формулу, пока не получите # ЧИСЛО! ошибки, означающие, что были перечислены все отсутствующие числа. Смотрите скриншот:

док-идентификация-отсутствующие-номера4


стрелка синий правый пузырь Определите последовательность пропущенных чисел с помощью Kutools for Excel быстро

Вышеупомянутые методы могут идентифицировать только отсутствующую чистую числовую последовательность, если у вас есть такая последовательность, как AA-1001-BB, AA-1002-BB, они могут не работать успешно. Но не волнуйся, Kutools for Excelмощная функция — Найти отсутствующий порядковый номер может помочь вам быстро определить недостающую последовательность.

Примечание:Чтобы применить это Найти отсутствующий порядковый номер, во-первых, вы должны скачать Kutools for Excel, а затем быстро и легко примените эту функцию.

После установки Kutools for Excel, пожалуйста, сделайте так:

1. Выберите последовательность данных, в которой вы хотите найти недостающую последовательность.

2. Нажмите Кутулс > Вставить > Найти отсутствующий порядковый номер, см. снимок экрана:

3. в Найти отсутствующий порядковый номер диалоговое окно:

(1.) Если вы выберете Вставка нового столбца со следующим отсутствующим маркером вариант, все недостающие порядковые номера отмечены текстом Отсутствующий в новом столбце рядом с вашими данными. Смотрите скриншот:

док-идентификация-отсутствующие-числа 6

(2.) Если вы выберете Вставка отсутствующего порядкового номера вариант, все недостающие числа были вставлены в список последовательностей. Смотрите скриншот:

док-идентификация-отсутствующие-числа 7

(3.) Если вы выберете Вставка пустых строк при включении отсутствующих порядковых номеров вариант, все пустые строки вставляются, когда отсутствуют числа. Смотрите скриншот:

док-идентификация-отсутствующие-числа 8

(4.) Если вы выберете Цвет заливки фона вариант, расположение недостающих номеров будет выделено сразу. Смотрите скриншот:

док-идентификация-отсутствующие-числа 9


стрелка синий правый пузырь Определите последовательность пропущенных чисел с помощью Kutools for Excel быстро


Лучшие инструменты для работы в офисе

Kutools for Excel Решит большинство ваших проблем и повысит вашу производительность на 80%

  • Снова использовать: Быстро вставить сложные формулы, диаграммы и все, что вы использовали раньше; Зашифровать ячейки с паролем; Создать список рассылки и отправлять электронные письма …
  • Бар Супер Формулы (легко редактировать несколько строк текста и формул); Макет для чтения (легко читать и редактировать большое количество ячеек); Вставить в отфильтрованный диапазон
  • Объединить ячейки / строки / столбцы без потери данных; Разделить содержимое ячеек; Объединить повторяющиеся строки / столбцы… Предотвращение дублирования ячеек; Сравнить диапазоны
  • Выберите Дубликат или Уникальный Ряды; Выбрать пустые строки (все ячейки пустые); Супер находка и нечеткая находка во многих рабочих тетрадях; Случайный выбор …
  • Точная копия Несколько ячеек без изменения ссылки на формулу; Автоматическое создание ссылок на несколько листов; Вставить пули, Флажки и многое другое …
  • Извлечь текст, Добавить текст, Удалить по позиции, Удалить пробел; Создание и печать промежуточных итогов по страницам; Преобразование содержимого ячеек в комментарии
  • Суперфильтр (сохранять и применять схемы фильтров к другим листам); Расширенная сортировка по месяцам / неделям / дням, периодичности и др .; Специальный фильтр жирным, курсивом …
  • Комбинируйте книги и рабочие листы; Объединить таблицы на основе ключевых столбцов; Разделить данные на несколько листов; Пакетное преобразование xls, xlsx и PDF
  • Более 300 мощных функций. Поддерживает Office/Excel 2007-2021 и 365. Поддерживает все языки. Простое развертывание на вашем предприятии или в организации. Полнофункциональная 30-дневная бесплатная пробная версия. 60-дневная гарантия возврата денег.

вкладка kte 201905


Вкладка Office: интерфейс с вкладками в Office и упрощение работы

  • Включение редактирования и чтения с вкладками в Word, Excel, PowerPoint, Издатель, доступ, Visio и проект.
  • Открывайте и создавайте несколько документов на новых вкладках одного окна, а не в новых окнах.
  • Повышает вашу продуктивность на 50% и сокращает количество щелчков мышью на сотни каждый день!

офисный дно

Improve Article

Save Article

Like Article

  • Read
  • Discuss
  • Improve Article

    Save Article

    Like Article

    Given a column in the table having values from 1 to N, one value will be missed. The task is to find the missing number.

    So, let’s start by creating a database first.

    Step 1 : Create Database.

    Query :

    CREATE DATABASE GFG

    Step 2 : Use the GFG Database.

    Query :

    USE GFG

    Step 3 : Create a table

    Create a table (MissingNumber) to store the data.

    Query :

    CREATE TABLE MissingNumber( Value INT );

    Output :

    Step 4 : Insert some data into the database.

    Query : 

    INSERT INTO MissingNumber
    VALUES 
      (1),
      (2), 
      (3), 
      (4),  
      (6), 
      (7), 
      (8);

    Output :

    Step 5 : SQL query to select the missing number in the column from 1 to N.

    Sum of numbers from 1 to N (S)= (N * (N+1)) / 2;

    The missing number will be the difference of S and the sum of values in the column.

    Query :

    SELECT ( (COUNT(Value)+1) * (COUNT(Value)+2) / 2) - SUM(Value) AS Missing FROM MissingNumber

    Output :

    In the MissingNumber table, 5 is the missing number in the Value column.

    Last Updated :
    02 Apr, 2023

    Like Article

    Save Article

    Время на прочтение
    2 мин

    Количество просмотров 32K

    Разработчики и администраторы систем основанных на sql данных, наверняка, сталкивались с задачей — получить отсутствующее (пропущенное) значение в ряде id записей таблицы. Например номер договора, порядковый номер документа, телефонный номер, айпи-адрес и т.п. При работе с MySQL эта тривиальная задача непропорционально ресурсоемка.

    Например, у нас есть пул внутренних телефонных номеров компании от 2001 до 2999 и таблица с выданными из них номерами для сотрудников:

    • t1.phone
    • 2001
    • 2002
    • 2003
    • 2004
    • 2005
    • 2009
    • 2015
    • 2016

    Нам нужно найти первое свободное значение (в данном случае 2006) чтобы выделить очередной номер очередному сотруднику. Если свободных значений нет, то нужно выделить следующий из диапазона. Знакомая задача? Решения, которыми изобилует интернет, сводятся к двум принципам:

    1) Делать перебор в цикле: например в SQL создать курсор CUR i+1 c 2001 до 2999 и делать запросы

    SELECT t1.phone FROM t1 WHERE phone = i

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

    2) Второй принцип, использовать LEFT (OUTER) JOIN последовательности 2001…2009 с таблицей t1 (WHERE t1.phone IS NULL конечно же), либо таблицы t1 с собой же со сдвигом на шаг:

    SELECT MIN(t1.phone)+1 FROM t1 LEFT JOIN t1 AS diff ON (t1.phone = diff.phone+1) WHERE diff.phone IS NULL

    Еще один вариант с использованием IN

    SELECT ... WHERE phone NOT IN (....)

    вообще не рассматриваю из-за громоздкости.

    На маленьких объемах данных оба решения (и даже с IN) прекрасно работают, а при большом количестве записей эти решения либо ресурсоемки, либо продолжительны во времени, либо и то и другое.
    Зависит от мощностей сервера и настроек базы, но в любом случае если перебирать миллион записей или приджойнить такую таблицу, даже на мощном сервере выполнение займет заметное время.

    Я же захотел решить задачу быстро, не напрягая сервер, и, желательно, в один запрос. В один, не в один, но вот что получилось:

    
    	/*выбираю граничные значения*/
    	select 2000,2999 into @num,@maxid;
    
    	select min(f.id) /* внешний селект дополнительный для "очистки" результата union */
    	from
    		(select s.num, min(s.num) /* первое расхождение рядов */ id
    		from (
    				select
    					/* формирую ряд, в данном случае арифм.прогрессия, но может быть с любым шагом, или вычисляемым */
    					@num:=@num+1 num,
    					/* выбираю занятые значения */
    					r.id 
    				from t1 as r
    				order by id
    			) as s
    		where 
    			/* применяю условие расхождения рядов */ s.id != s.num /* причем ряды разойдутся и расхождение будет постоянным, поэтому во внешнем селекте использую только первое расхождение - min */
    		/* если расхождения не было, добавляю еще одно возможное значение из диапазона граничных значений либо null, если значения закончились */
    		union
    		select @num+1 num, if(@num+1<@maxid,@num+1,null) id
    		) as f
    	where /* очищаю лишние результаты union */
    		f.id is not null
    	limit 1;
    

    По сравнению с джойнами простые селекты выполняются в сотни раз быстрее.

    Понятное дело, что такое решение известно, но в интернетах, как ни странно, с наскока его найти не удалось, вот и хочу поделиться эти простым «велосипедом».

    UPD.
    Прекрасное решение подсказал в личке участник stepmex
    Без всякого дополнительного построения нумерации и сравнений рядов, изящно решил задачу через (SELECT 1 …..) IS NULL
    Великолепная находка, я считаю:

    
    SELECT (`t1`.`phone`+1) as `empty_phone`
    FROM `t1`
    WHERE (
    	SELECT 1 FROM `t1` as `st` WHERE `st`.`phone` = (`t1`.`phone` + 1)
    ) IS NULL
    ORDER BY `t1`.`phone`
    LIMIT 1
    

    Понравилась статья? Поделить с друзьями:
  • Как найти свой shsh
  • Pathfinder kingmaker тартуччио как найти
  • Спп это как найти
  • Если не получились подтеки на торте как исправить
  • Как найти потерянную вещь онлайн гадание