Как мне создать ряд последовательных чисел (по одной в строке) из запроса MySQL, чтобы я мог вставлять их в таблицу?
Например:
nr
1
2
3
4
5
Я хотел бы использовать для этого только MySQL (не PHP или другие языки).
Как мне создать ряд последовательных чисел (по одной в строке) из запроса MySQL, чтобы я мог вставлять их в таблицу?
Например:
nr
1
2
3
4
5
Я хотел бы использовать для этого только MySQL (не PHP или другие языки).
Если вам нужны записи в таблице, и вы хотите избежать проблем с concurrency, вот как это сделать.
Сначала вы создаете таблицу для хранения ваших записей
CREATE TABLE `incr` (
`Id` int(11) NOT NULL auto_increment,
PRIMARY KEY (`Id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Во-вторых, создайте хранимую процедуру следующим образом:
DELIMITER ;;
CREATE PROCEDURE dowhile()
BEGIN
DECLARE v1 INT DEFAULT 5;
WHILE v1 > 0 DO
INSERT incr VALUES (NULL);
SET v1 = v1 - 1;
END WHILE;
END;;
DELIMITER ;
Наконец, вызовите SP:
CALL dowhile();
SELECT * FROM incr;
Результат
Id
1
2
3
4
5
Вот один из способов сделать это на основе набора без циклов. Это также можно сделать в виде для повторного использования. В этом примере показана генерация последовательности от 0 до 999, но, разумеется, она может быть изменена, чтобы она соответствовала.
INSERT INTO
myTable
(
nr
)
SELECT
SEQ.SeqValue
FROM
(
SELECT
(HUNDREDS.SeqValue + TENS.SeqValue + ONES.SeqValue) SeqValue
FROM
(
SELECT 0 SeqValue
UNION ALL
SELECT 1 SeqValue
UNION ALL
SELECT 2 SeqValue
UNION ALL
SELECT 3 SeqValue
UNION ALL
SELECT 4 SeqValue
UNION ALL
SELECT 5 SeqValue
UNION ALL
SELECT 6 SeqValue
UNION ALL
SELECT 7 SeqValue
UNION ALL
SELECT 8 SeqValue
UNION ALL
SELECT 9 SeqValue
) ONES
CROSS JOIN
(
SELECT 0 SeqValue
UNION ALL
SELECT 10 SeqValue
UNION ALL
SELECT 20 SeqValue
UNION ALL
SELECT 30 SeqValue
UNION ALL
SELECT 40 SeqValue
UNION ALL
SELECT 50 SeqValue
UNION ALL
SELECT 60 SeqValue
UNION ALL
SELECT 70 SeqValue
UNION ALL
SELECT 80 SeqValue
UNION ALL
SELECT 90 SeqValue
) TENS
CROSS JOIN
(
SELECT 0 SeqValue
UNION ALL
SELECT 100 SeqValue
UNION ALL
SELECT 200 SeqValue
UNION ALL
SELECT 300 SeqValue
UNION ALL
SELECT 400 SeqValue
UNION ALL
SELECT 500 SeqValue
UNION ALL
SELECT 600 SeqValue
UNION ALL
SELECT 700 SeqValue
UNION ALL
SELECT 800 SeqValue
UNION ALL
SELECT 900 SeqValue
) HUNDREDS
) SEQ
Здесь версия инженерного инженера Pittsburgh DBA:
SELECT
(TWO_1.SeqValue + TWO_2.SeqValue + TWO_4.SeqValue + TWO_8.SeqValue + TWO_16.SeqValue) SeqValue
FROM
(SELECT 0 SeqValue UNION ALL SELECT 1 SeqValue) TWO_1
CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 2 SeqValue) TWO_2
CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 4 SeqValue) TWO_4
CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 8 SeqValue) TWO_8
CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 16 SeqValue) TWO_16;
Предположим, вы хотите вставить числа 1 - 100 в таблицу. До тех пор, пока у вас есть другая таблица, которая содержит по крайней мере столько строк (не имеет значения содержимое таблицы), это мой предпочтительный метод:
INSERT INTO pivot100
SELECT @ROW := @ROW + 1 AS ROW
FROM someOtherTable t
join (SELECT @ROW := 0) t2
LIMIT 100
;
Хотите диапазон, начинающийся с чего-то другого, кроме 1? Просто измените настройки @ROW на соединение.
Как вы все понимаете, это довольно хаки, поэтому используйте с осторожностью
SELECT id % 12 + 1 as one_to_twelve FROM any_large_table group by one_to_twelve
DECLARE i INT DEFAULT 0;
WHILE i < 6 DO
/* insert into table... */
SET i = i + 1;
END WHILE;
"Самый короткий" способ, которым я знаю (в MySQL) создать таблицу с длинной последовательностью, - это (крест) присоединиться к существующей таблице с самим собой. Поскольку любой (общий) сервер MySQL имеет таблицу information_schema.COLUMNS
, я бы использовал его:
DROP TABLE IF EXISTS seq;
CREATE TABLE seq (i MEDIUMINT AUTO_INCREMENT PRIMARY KEY)
SELECT NULL AS i
FROM information_schema.COLUMNS t1
JOIN information_schema.COLUMNS t2
JOIN information_schema.COLUMNS t3
LIMIT 100000; -- <- set your limit here
Обычно одного соединения должно быть достаточно, чтобы создать более 1 М строк. Но еще одно соединение не повредит:-) - Просто не забудьте установить предел.
Если вы хотите включить 0
, вы должны "удалить" свойство AUTO_INCEMENT
.
ALTER TABLE seq ALTER i DROP DEFAULT;
ALTER TABLE seq MODIFY i MEDIUMINT;
Теперь вы можете вставить 0
INSERT INTO seq (i) VALUES (0);
и отрицательные числа, а также
INSERT INTO seq (i) SELECT -i FROM seq WHERE i <> 0;
Вы можете проверить числа с помощью
SELECT MIN(i), MAX(i), COUNT(*) FROM seq;
Идея, которую я хочу рассказать, не является точным ответом на вопрос, но может быть полезна для некоторых, поэтому я хотел бы поделиться им.
Если вам часто нужен только ограниченный набор чисел, тогда полезно создать таблицу с числами, которые могут вам понадобиться, и просто использовать эту таблицу каждый раз. Например:
CREATE TABLE _numbers (num int);
INSERT _numbers VALUES (0), (1), (2), (3), ...;
Это можно применять только в том случае, если вам нужны номера ниже определенного разумного предела, поэтому не используйте его для генерации последовательности 1... 1 млн, но могут использоваться, например, для чисел 1... 10k.
Если у вас есть этот список чисел в таблице _numbers
вы можете писать запросы, подобные этому, для получения отдельных символов строки:
SELECT number, substr(name, num, 1)
FROM users
JOIN _numbers ON num < length(name)
WHERE user_id = 1234
ORDER BY num;
Если вам нужно большее количество, чем 10k, вы можете присоединиться к таблице:
SELECT n1.num * 10000 + n2.num
FROM _numbers n1
JOIN _numbers n2
WHERE n1 < 100
ORDER BY n1.num * 10000 + n2.num; -- or just ORDER BY 1 meaning the first column