У нас есть база данных с таблицей, значения которой были импортированы из другой системы. Есть столбец с автоинкрементом, нет повторяющихся значений, но есть пропущенные значения. Например, при выполнении этого запроса:
select count(id) from arrc_vouchers where id between 1 and 100
должен вернуть 100, но вместо этого возвращает 87. Могу ли я выполнить какой-либо запрос, который вернет значения отсутствующих чисел? Например, записи могут существовать для идентификаторов 1-70 и 83-100, но отсутствуют записи с идентификаторами 71-82. Хочу вернуть 71, 72, 73 и т. Д.
Это возможно?
mysql
sql
gaps-and-islands
Emmys
источник
источник
select l.id + 1 as start from sequence as l left outer join sequence as r on l.id + 1 = r.id where r.id is null;
Ответы:
Обновить
ConfexianMJS дал гораздо лучший ответ с точки зрения производительности.
Ответ (не самый быстрый)
Вот версия, которая работает с таблицей любого размера (а не только со 100 строками):
gap_starts_at
- первый id в текущем промежуткеgap_ends_at
- последний id в текущем промежуткеисточник
order number
я искал пробелы в неразличимых (таблица хранит строки заказов, поэтому номер заказа, которому они принадлежат, повторяется для каждой строки). 1-й запрос: 2812 строк в наборе (1 мин 31,09 сек) . Сделал еще одну таблицу, выбрав отдельные номера заказов. Ваш запрос без моих повторов: 1009 строк в наборе (18,04 сек)SELECT MIN(id) FROM table
?Это помогло мне найти пробелы в таблице с более чем 80 тыс. Строк:
Результат:
Обратите внимание, что порядок столбцов
expected
иgot
имеет решающее значение.Если вы знаете, что
YourCol
он не начинается с 1 и это не имеет значения, вы можете заменитьс участием
Новый результат:
Если вам нужно выполнить какую-то задачу сценария оболочки с отсутствующими идентификаторами, вы также можете использовать этот вариант, чтобы напрямую создать выражение, которое вы можете перебирать в bash.
Это дает такой результат
Затем вы можете скопировать и вставить его в цикл for в терминале bash, чтобы выполнить команду для каждого идентификатора.
Это то же самое, что и выше, только читаемое и исполняемое. Изменив команду «CONCAT» выше, можно сгенерировать синтаксис для других языков программирования. Или даже SQL.
источник
CONVERT( YourCol, UNSIGNED )
что даст лучшие результаты, если YourCol еще не является целым числом.SELECT MAX(YourCol) FROM YourTable;
SELECT IF((z.got-IF(z.over>0, z.over, 0)-1)>z.expected, CONCAT(z.expected,' thru ',(z.got-IF(z.over>0, z.over, 0)-1)), z.expected) AS missing FROM ( SELECT @rownum:=@rownum+1 AS expected, @target-@missing AS under, (@missing:=@missing+IF(@rownum=YourCol, 0, YourCol-@rownum))-@target AS over, IF(@rownum=YourCol, 0, @rownum:=YourCol) AS got FROM (SELECT @rownum:=0, @missing:=0, @target:=10) AS a JOIN YourTable ORDER BY YourCol ) AS z WHERE z.got!=0 AND z.under>0;
Быстрый и грязный запрос, который должен помочь:
Это даст вам таблицу, показывающую идентификатор, над которым отсутствуют идентификаторы, и next_id, который существует, и сколько их отсутствует между ... например
источник
Если вы используете, у
MariaDB
вас есть более быстрый (800%) вариант с использованием механизма хранения последовательностей :источник
"SELECT MAX(column) FROM table"
и установив переменную из результата, скажем, $ MAX ... затем можно написать оператор sql,"SELECT * FROM seq_1_to_". $MAX ." WHERE seq not in (SELECT column FROM table)"
мой синтаксис основан на phpSELECT @var:= max FROM ....; select * from .. WHERE seq < @max;
с переменными MySQL.Создайте временную таблицу со 100 строками и одним столбцом, содержащим значения 1–100.
Внешний Присоедините эту таблицу к вашей таблице arrc_vouchers и выберите значения одного столбца, в которых идентификатор arrc_vouchers равен нулю.
Кодирование это вслепую, но должно работать.
источник
Альтернативным решением, требующим запроса + некоторого кода, выполняющего некоторую обработку, было бы:
Обратите внимание, что запрос не содержит подзапроса, который, как мы знаем, не обрабатывается планировщиком MySQL эффективно.
Это вернет одну запись на центральное значение (cValue), которое не имеет меньшего значения (lValue) или большего значения (rValue), то есть:
Не вдаваясь в подробности (мы увидим их в следующих параграфах), этот вывод означает, что:
Таким образом, основная идея состоит в том, чтобы выполнить соединения RIGHT и LEFT с одной и той же таблицей, чтобы увидеть, есть ли у нас значения смежности для каждого значения (например, если центральное значение равно '3', тогда мы проверяем 3-1 = 2 слева и 3 + 1 в right), а когда ROW имеет значение NULL в RIGHT или LEFT, мы знаем, что смежного значения нет.
Полный необработанный вывод моей таблицы:
Некоторые примечания:
источник
Если существует последовательность, в которой между двумя числами пробел не превышает единицы (например, 1,3,5,6), то можно использовать следующий запрос:
source1
id
источник
на основе ответа, приведенного выше Лучеком, эта хранимая процедура позволяет вам указать имена таблиц и столбцов, которые вы хотите протестировать, чтобы найти несмежные записи - таким образом, отвечая на исходный вопрос, а также демонстрируя, как можно использовать @var для представления таблиц и / или столбцы в хранимой процедуре.
источник
Я пробовал это разными способами, и лучшая производительность, которую я обнаружил, была это простой запрос:
... одно левое соединение, чтобы проверить, существует ли следующий идентификатор , только если следующий, если не найден, тогда подзапрос находит следующий идентификатор, который существует, чтобы найти конец пробела. Я сделал это, потому что запрос с равным (=) имеет лучшую производительность, чем оператор больше (>).
Используя sqlfiddle, он не показывает такую разную производительность по сравнению с другими запросами, но в реальной базе данных этот запрос выше приводит в 3 раза быстрее, чем другие.
Схема:
Следуйте ниже всем запросам, которые я сделал для сравнения производительности:
Может кому поможет и пригодится.
Вы можете увидеть и протестировать мой запрос, используя этот sqlfiddle :
http://sqlfiddle.com/#!9/6bdca7/1
источник
Хотя кажется, что все это работает, набор результатов возвращается через очень долгое время, когда имеется 50 000 записей.
Я использовал это, и он находит пробел или следующий доступный (последний использованный + 1) с гораздо более быстрым возвратом из запроса.
источник
Возможно, это не актуально, но я искал что-то вроде этого, чтобы перечислить пробелы в последовательности чисел, и нашел этот пост, в котором есть несколько разных решений в зависимости от того, что именно вы ищете. Я искал первый доступный пробел в последовательности (то есть следующий доступный номер), и, похоже, это работает нормально.
ВЫБЕРИТЕ MIN (l.number_sequence + 1) как nextavabile из пациентов как l LEFT OUTER JOIN пациентов как r на l.number_sequence + 1 = r.number_sequence ГДЕ r.number_sequence имеет значение NULL. Там обсуждались еще несколько сценариев и решений, начиная с 2005 года!
Как найти пропущенные значения в последовательности с помощью SQL
источник