Как вы можете найти пробелы ID в наборе записей MySQL? - PullRequest
5 голосов
/ 09 декабря 2011

Проблема здесь связана с другим вопросом, который у меня был ...

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

Я хочу найти пропуски и повторно использовать оставленные идентификаторы.

Какой эффективный способ сделать это в MySQL?

Ответы [ 4 ]

17 голосов
/ 09 декабря 2011

Прежде всего, какое преимущество вы пытаетесь получить, повторно используя пропущенные значения?Обычный INT UNSIGNED позволит вам сосчитать до 4 294 967 295.С «миллионами записей» ваша база данных должна была бы вырасти в тысячу раз, прежде чем закончатся действительные идентификаторы.(А затем использование BIGINT UNSIGNED приведет к увеличению до 18 446 744 073 709 551 615 значений.)

Попытка перезапустить значения, которые MySQL пропустил, вероятно, потребует много вашего времени, пытаясь компенсировать то, что на самом деле неВо-первых, беспокоить MySQL.

С учетом сказанного вы можете найти пропущенные идентификаторы с чем-то вроде:

SELECT id + 1
FROM the_table
WHERE NOT EXISTS (SELECT 1 FROM the_table t2 WHERE t2.id = the_table.id + 1);

Это позволит найти только пропущенное число first вкаждая последовательность (например, если у вас есть {1, 2, 3, 8, 10}, она найдет {4,9}), но она, вероятно, будет эффективной, и, конечно, после ввода идентификатора вы всегда можете запустить ее снова.

2 голосов
/ 30 декабря 2012

Следующая строка будет возвращать строку для каждого пробела в целочисленном поле «n» в mytab:

/* cs will contain 1 row for each contiguous sequence of integers in mytab.n
   and will have the start of that chain.
   ce will contain the end of that chain */
create temporary table cs (row int auto_increment primary key, n int);
create temporary table ce like cs;
insert into cs (n) select n from mytab where n-1 not in (select n from mytab) order by n;
insert into ce (n) select n from mytab where n+1 not in (select n from mytab) order by n;
select ce.n + 1 as bgap, cs.n - 1 as egap
  from cs, ce where cs.row = ce.row + 1;

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

select cs.n as bchain, ce.n as echain from cs,ce where cs.row=ce.row;
1 голос
/ 17 июня 2013

Это решение лучше, если вам нужно включить первый элемент как 1:

SELECT
    1 AS gap_start,
    MIN(e.id) - 1 AS gap_end
FROM
    factura_entrada e
WHERE
    NOT EXISTS(
        SELECT
            1
        FROM
            factura_entrada
        WHERE
            id = 1
    )
LIMIT 1
UNION
    SELECT
        a.id + 1 AS gap_start,
        MIN(b.id)- 1 AS gap_end
    FROM
        factura_entrada AS a,
        factura_entrada AS b
    WHERE
        a.id < b.id
    GROUP BY
        a.id
    HAVING
        gap_start < MIN(b.id);
0 голосов
/ 10 января 2017

Если вы используете MariaDB, у вас есть более быстрый вариант

SELECT * FROM seq_1_to_50000 where seq not in (select col from table);

документы: https://mariadb.com/kb/en/mariadb/sequence/

...