如何从MySQL查询中生成一系列连续数字(每行一个),以便我可以将它们插入表格中?
例如:
nr
1
2
3
4
5
我想只使用MySQL(不是PHP或其他语言)。
答案 0 :(得分:60)
这是一种基于集合的方法,没有循环。这也可以作为重复使用的视图。该示例显示了从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
答案 1 :(得分:47)
这是硬件工程师的Pittsburgh DBA's solution版本:
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;
答案 2 :(得分:28)
如果您需要表中的记录并且希望避免并发问题,请按照以下步骤操作。
首先,您要创建一个用于存储记录的表
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
答案 3 :(得分:13)
我们假设您要在表格中插入数字1到100。只要你有一些其他表至少包含那么多行(表格的内容并不重要),那么这是我首选的方法:
INSERT INTO pivot100
SELECT @ROW := @ROW + 1 AS ROW
FROM someOtherTable t
join (SELECT @ROW := 0) t2
LIMIT 100
;
想要一个以1以外的东西开头的范围?只需更改@ROW在连接上设置的内容。
答案 4 :(得分:5)
DECLARE i INT DEFAULT 0;
WHILE i < 6 DO
/* insert into table... */
SET i = i + 1;
END WHILE;
答案 5 :(得分:5)
大家都明白,这是相当黑客的,所以要小心使用
SELECT id % 12 + 1 as one_to_twelve FROM any_large_table group by one_to_twelve
答案 6 :(得分:0)
我知道(在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
通常一个连接应该足以创建超过1M的行 - 但是还有一个连接不会受到影响:-) - 只是不要忘记设置限制。
如果您想加入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;
答案 7 :(得分:0)
我想分享的想法不是对问题的准确回答,但对某些人有用,所以我想分享它。
如果您经常只需要一组有限的数字,那么创建一个包含您可能需要的数字的表格并且每次只使用该表格都是有益的。例如:
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
答案 8 :(得分:0)
与接受的响应非常相似,但是对mysql> = 8.0使用了新的WITH
语法,这使它更加清晰易读,意图也更加清晰
WITH DIGITS (N) AS (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL
SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL
SELECT 8 UNION ALL SELECT 9)
SELECT
UNITS.N + TENS.N*10 + HUNDREDS.N*100 + THOUSANDS.N*1000
FROM
DIGITS AS UNITS, DIGITS AS TENS, DIGITS AS HUNDREDS, DIGITS AS THOUSANDS;
答案 9 :(得分:0)
这基于先前的答案(https://stackoverflow.com/a/53125278/2009581),但与MySQL 5.7兼容。它适用于副本和只读用户:
var city = {};
$('.ville-select option').each(function() {
var val = $(this).val();
if (city[val]) {
$(this).remove();
return;
}
city[val] = 1;
});
它会生成[0,SELECT x1.N + x10.N*10 + x100.N*100 + x1000.N*1000
FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) x1,
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) x10,
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) x100,
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) x1000
WHERE x1.N + x10.N*10 + x100.N*100 + x1000.N*1000 <= @max;
]范围内的整数。
答案 10 :(得分:0)
所有其他答案都不错,但是它们都存在较大范围的速度问题,因为它们迫使MySQL生成每个数字然后对其进行过滤。
以下内容仅使MySQL生成所需的数字,因此速度更快:
set @amount = 55; # How many numbers from zero you want to generate
select `t0`.`i`+`t1`.`i`+`t2`.`i`+`t3`.`i` as `offset`
from
(select 0 `i` 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) `t0`,
(select 0 `i` union select 10 union select 20 union select 30 union select 40 union select 50 union select 60 union select 70 union select 80 union select 90) `t1`,
(select 0 `i` union select 100 union select 200 union select 300 union select 400 union select 500 union select 600 union select 700 union select 800 union select 900) `t2`,
(select 0 `i` union select 1000 union select 2000 union select 3000 union select 4000 union select 5000 union select 6000 union select 7000 union select 8000 union select 9000) `t3`
where `t3`.`i`<@amount
and `t2`.`i`<@amount
and `t1`.`i`<@amount
and `t0`.`i`+`t1`.`i`+`t2`.`i`+`t3`.`i`<@amount;
使用上述方法,您最多可以生成10,000个数字(0到9,999),而对于较低的数字,无论它们有多低,都不会降低速度。
答案 11 :(得分:0)
如果您有 MySql 8 及更高版本,这里有一种使用 json_table 的方法:
set @noRows = 100;
SELECT tt.rowid - 1 AS value
FROM JSON_TABLE(CONCAT('[{}', REPEAT(',{}', @noRows - 1), ']'),
"$[*]" COLUMNS(rowid FOR ORDINALITY)
) AS tt;
(h/t - https://www.percona.com/blog/2020/07/27/generating-numeric-sequences-in-mysql/)
答案 12 :(得分:0)
使用递归 cte..
with recursive rnums as (
select 1 as n
union all
select n+1 as n from rnums
where n <10
)
select * from rnums
;
结果是.. +------+ | | | +------+ | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 | | 8 | | 9 | | 10 | +------+ 10 行(0.00 秒)