генерировать целочисленную последовательность в MySQL - PullRequest
50 голосов
/ 20 ноября 2008

Мне нужно сделать соединение с таблицей / результирующим набором / всем, что имеет целые числа от n до m включительно. Есть ли тривиальный способ получить это, не просто создавая стол?

(Кстати, как будет называться этот тип конструкции, «мета-запрос»?)

м-н ограничен чем-то разумным (<1000) </p>

Ответы [ 16 ]

2 голосов
/ 20 ноября 2008

Насколько большой м?

Вы можете сделать что-то вроде:

create table two select null foo union all select null;
create temporary table seq ( foo int primary key auto_increment ) auto_increment=9 select a.foo from two a, two b, two c, two d;
select * from seq where foo <= 23;

, где auto_increment установлен в n, а предложение where сравнивается с m, и число повторений двух таблиц составляет по меньшей мере ceil (log (m-n + 1) / log (2)).

(Невременные две таблицы можно было бы опустить, заменив две на (выберите null, foo union all выберите null) в следующей последовательности создания временной таблицы.)

1 голос
/ 19 июля 2018

Самый простой способ сделать это:

SET @seq := 0;
SELECT @seq := FLOOR(@seq + 1) AS sequence, yt.*
FROM your_table yt;

или в одном запросе:

SELECT @seq := FLOOR(@seq + 1) AS sequence, yt.*
FROM (SELECT @seq := 0) s, your_table yt;

Функция FLOOR() используется здесь для получения INTEGER вместо FLOAT. Иногда это необходимо.

Мой ответ был вдохновлен Дэвид Бедный ответ . Спасибо Дэвид!

1 голос
/ 30 декабря 2008

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

Вы можете получить это значение до O (log N), используя временную таблицу (для вставки чисел от 10000 до 10699 см. Ниже):

mysql> CREATE TABLE `tmp_keys` (`k` INTEGER UNSIGNED, PRIMARY KEY (`k`));
Query OK, 0 rows affected (0.11 sec)

mysql> INSERT INTO `tmp_keys` VALUES (0),(1),(2),(3),(4),(5),(6),(7);
Query OK, 8 rows affected (0.03 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> INSERT INTO `tmp_keys` SELECT k+8 from `tmp_keys`;
Query OK, 8 rows affected (0.02 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> INSERT INTO `tmp_keys` SELECT k+16 from `tmp_keys`;
Query OK, 16 rows affected (0.03 sec)
Records: 16  Duplicates: 0  Warnings: 0

mysql> INSERT INTO `tmp_keys` SELECT k+32 from `tmp_keys`;
Query OK, 32 rows affected (0.03 sec)
Records: 32  Duplicates: 0  Warnings: 0

mysql> INSERT INTO `tmp_keys` SELECT k+64 from `tmp_keys`;
Query OK, 64 rows affected (0.03 sec)
Records: 64  Duplicates: 0  Warnings: 0

mysql> INSERT INTO `tmp_keys` SELECT k+128 from `tmp_keys`;
Query OK, 128 rows affected (0.05 sec)
Records: 128  Duplicates: 0  Warnings: 0

mysql> INSERT INTO `tmp_keys` SELECT k+256 from `tmp_keys`;
Query OK, 256 rows affected (0.03 sec)
Records: 256  Duplicates: 0  Warnings: 0

mysql> INSERT INTO `tmp_keys` SELECT k+512 from `tmp_keys`;
Query OK, 512 rows affected (0.11 sec)
Records: 512  Duplicates: 0  Warnings: 0

mysql> INSERT INTO inttable SELECT k+10000 FROM `tmp_keys` WHERE k<700;
Query OK, 700 rows affected (0.16 sec)
Records: 700  Duplicates: 0  Warnings: 0

edit: fyi, к сожалению, это не будет работать с истинной временной таблицей с MySQL 5.0 , так как она не может вставляться в себя (вы можете прыгать назад и вперед между двумя временными таблицами).

edit: Вы могли бы использовать MEMORY Storage Engine , чтобы предотвратить это на самом деле истощение "реальной" базы данных. Интересно, разработал ли кто-нибудь механизм виртуального хранения NUMBERS для создания виртуального хранилища для создания таких последовательностей, как этот. (увы, непортативный вне MySQL)

1 голос
/ 21 ноября 2008

Похоже, вы можете создавать достаточно большие наборы с:

select 9 union all select 10 union all select 11 union all select 12 union all select 13 ...

Я получил переполнение стека парсера в 5300 на 5.0.51a.

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

Счетчик от 1 до 1000:

  • нет необходимости создавать таблицу
  • время выполнения ~ 0,0014 сек
  • можно преобразовать в представление

:

select tt.row from
(
SELECT cast( concat(t.0,t2.0,t3.0,t4.0) + 1 As UNSIGNED) as 'row' FROM 
(select 0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t,
(select 0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2, 
(select 0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3
) tt
order by tt.row

Кредиты: ответ , комментарий Сета МакКоли под ответом.

0 голосов
/ 30 декабря 2008

Если бы вы использовали Oracle, «конвейерные функции» были бы подходящим вариантом. К сожалению, MySQL не имеет такой конструкции.

В зависимости от масштаба чисел, наборы которых вы хотите, я вижу два простых способа: вы либо заполняете временную таблицу только теми числами, которые вам нужны (возможно, используя таблицы памяти, заполненные хранимой процедурой) для одного запрос или, заранее, вы создаете большую таблицу, которая насчитывает от 1 до 1 000 000, и выбираете ее ограниченные области.

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