在MySQL中生成一个整数序列

BCS*_*BCS 55 mysql

我需要使用表/结果集/具有整数n到m的任何内容进行连接.有没有一种简单的方法来获得它而不仅仅是建立表格?

(顺便说一句,那种类型的构造会被称为"元查询"?)

mn受限于某种合理的(<1000)

小智 98

我在网上找到了这个解决方案

SET @row := 0;
SELECT @row := @row + 1 as row, t.*
FROM some_table t, (SELECT @row := 0) r
Run Code Online (Sandbox Code Playgroud)

单个查询,快速,并且完全符合我的要求:现在我可以"编号"从复杂查询中找到的"选择",其中唯一数字从1开始,并为结果中的每一行递增一次.

我认为这也适用于上面列出的问题:调整初始起始值@row并添加限制子句以设置最大值.

顺便说一句:我认为"r"并不是真正需要的.

DDSP

  • 选择的行数来自`some_table`而不是r.如果some_table没有行,则什么也得不到.我用这个来生成一组只需要名称和密码的测试数据.数字序列成为名称,密码只是ENCRYPT('passwd')所以它们都是相同的.为了生成行,我从另一个表中选择,但实际上没有选择任何列.它只给了我一行"some_table"中的每一行,所有这些都带有连续数字. (8认同)
  • 是的`r`是必需的 - 错误1248:每个派生表必须有自己的别名 (7认同)
  • +很多,我有点震惊 - 不知道MySQL可以做到这一点.这两个单独的查询可用于重新排序表的子集:`SET @row:= 0`和`UPDATE foo SET position =(@row:= @row + 1)WHERE <conditions> ORDER BY last_modified ASC` (5认同)

Unr*_*son 33

以下将返回1..10000并且不会那么慢

SELECT @row := @row + 1 AS row FROM 
(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) t,
(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) t2, 
(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) t3, 
(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) t4, 
(SELECT @row:=0) numbers;
Run Code Online (Sandbox Code Playgroud)

  • 一个解释会很好 - "t - t4"每个包含10行虚拟数据,这些的笛卡尔积为10 ^ 4,即10000行虚拟数据,而外部选择只是rownumber的mysql版本 (9认同)
  • 您可以通过将“ @row:= @row + 1 as row”替换为“ concat(t.0,t2.0,t3.0,t4.0)+ 1 as row”来摆脱变量声明,然后进行排序通过“行”。为了获得准确的结果,您还需要将每个子查询中重复的“选择6”更改为“选择2”(“ 2”当前未使用,但“ 6”被列出两次)。作为奖励,您还可以将每个“全部联合”缩短为“联合”,因为不再有任何重复的行。 (2认同)

O. *_*nes 18

如果您碰巧使用MySQLMariaDB分支,SEQUENCE引擎允许直接生成数字序列.它通过使用虚拟(假)一列表来实现.

例如,要生成从1到1000的整数序列,请执行此操作

     SELECT seq FROM seq_1_to_1000;
Run Code Online (Sandbox Code Playgroud)

对于0到11,执行此操作.

     SELECT seq FROM seq_0_to_11;
Run Code Online (Sandbox Code Playgroud)

对于从今天开始的一周的连续DATE值,请执行此操作.

SELECT FROM_DAYS(seq + TO_DAYS(CURDATE)) dateseq FROM seq_0_to_6
Run Code Online (Sandbox Code Playgroud)

DATE从'2010-01-01'开始,连续十年的价值是这样做的.

SELECT FROM_DAYS(seq + TO_DAYS('2010-01-01')) dateseq
  FROM seq_0_to_3800
 WHERE FROM_DAYS(seq + TO_DAYS('2010-01-01')) < '2010-01-01' + INTERVAL 10 YEAR
Run Code Online (Sandbox Code Playgroud)

如果您没有使用MariaDB,请考虑一下.


Aja*_*aju 12

试试这个..它在mysql 8.0版中对我有用。您可以根据您需要的范围修改以下查询

WITH recursive numbers AS (
    select 0 as Date
   union all
   select Date + 1
   from numbers
   where Date < 10)
select * from numbers;
Run Code Online (Sandbox Code Playgroud)

是的,没有像您的帖子中提到的那样创建表格

  • 不错的解决方案,但是,这适用于小于 1000 的数字,这是“cte_max_recursion_depth”的默认值 (3认同)

Eug*_*ota 7

MySQL中没有序列号生成器(CREATE SEQUENCE).最近的是AUTO_INCREMENT,它可以帮助你构建表.


Joh*_*son 5

你可以尝试这样的事情:

SELECT @rn:=@rn+1 as n
FROM (select @rn:=2)t, `order` rows_1, `order` rows_2 --, rows_n as needed...
LIMIT 4
Run Code Online (Sandbox Code Playgroud)

其中order只是一些具有相当大的行集的表的示例.

编辑:原来的答案是错误的,任何功劳应归功于David Poor,他提供了相同概念的实例


Cor*_*rax 5

有一种方法可以在单个查询中获取一系列值,但它有点慢。可以通过使用缓存表来加速。

假设您想要一个包含所有 BOOLEAN 值范围的选择:

SELECT 0 as b UNION SELECT 1 as b;
Run Code Online (Sandbox Code Playgroud)

我们可以发表看法

CREATE VIEW ViewBoolean AS SELECT 0 as b UNION SELECT 1 as b;
Run Code Online (Sandbox Code Playgroud)

那么你可以做一个字节

CREATE VIEW ViewByteValues AS
SELECT b0.b + b1.b*2 + b2.b*4 + b3.b*8 + b4.b*16 + b5.b*32 + b6.b*64 + b7.b*128 as v FROM
ViewBoolean b0,ViewBoolean b1,ViewBoolean b2,ViewBoolean b3,ViewBoolean b4,ViewBoolean b5,ViewBoolean b6,ViewBoolean b7;
Run Code Online (Sandbox Code Playgroud)

那么你可以做一个

CREATE VIEW ViewInt16 AS
SELECT b0.v + b1.v*256 as v FROM
ViewByteValues b0,ViewByteValues b1;
Run Code Online (Sandbox Code Playgroud)

那么你可以做一个

SELECT v+MIN as x FROM ViewInt16 WHERE v<MAX-MIN;
Run Code Online (Sandbox Code Playgroud)

为了加快速度,我跳过了字节值的自动计算,并将自己设置为

CREATE VIEW ViewByteValues AS
SELECT 0 as v UNION SELECT 1 as v UNION SELECT ...
...
...254 as v UNION SELECT 255 as v;
Run Code Online (Sandbox Code Playgroud)

如果您需要一系列日期,您可以这样做。

SELECT DATE_ADD('start_date',v) as day FROM ViewInt16 WHERE v<NumDays;
Run Code Online (Sandbox Code Playgroud)

或者

SELECT DATE_ADD('start_date',v) as day FROM ViewInt16 WHERE day<'end_date';
Run Code Online (Sandbox Code Playgroud)

您也许可以使用稍微快一点的 MAKEDATE 函数来加快速度

SELECT MAKEDATE(start_year,1+v) as day FRON ViewInt16 WHERE day>'start_date' AND day<'end_date';
Run Code Online (Sandbox Code Playgroud)

请注意,这个技巧非常慢,并且只允许在预定义域中创建有限序列(例如 int16 = 0...65536 )

我确信您可以通过提示 MySQL 在哪里停止计算来稍微修改查询以加快速度;)(使用 ON 子句而不是 WHERE 子句之类的东西)

例如:

SELECT MIN + (b0.v + b1.v*256 + b2.v*65536 + b3.v*16777216) FROM
ViewByteValues b0,
ViewByteValues b1,
ViewByteValues b2,
ViewByteValues b3
WHERE (b0.v + b1.v*256 + b2.v*65536 + b3.v*16777216) < MAX-MIN;
Run Code Online (Sandbox Code Playgroud)

会让你的 SQL 服务器忙碌几个小时

然而

SELECT MIN + (b0.v + b1.v*256 + b2.v*65536 + b3.v*16777216) FROM
ViewByteValues b0
INNER JOIN ViewByteValues b1 ON (b1.v*256<(MAX-MIN))
INNER JOIN ViewByteValues b2 ON (b2.v*65536<(MAX-MIN))
INNER JOIN ViewByteValues b3 ON (b3.v*16777216<(MAX-MIN)
WHERE (b0.v + b1.v*256 + b2.v*65536 + b3.v*16777216) < (MAX-MIN);
Run Code Online (Sandbox Code Playgroud)

将会运行得相当快 - 即使 MAX-MIN 很大,只要你用 LIMIT 1,30 或其他东西限制结果。但是 COUNT(*) 会花费很长时间,如果您在 MAX-MIN 大于 100k 时错误地添加 ORDER BY,那么计算将再次花费几秒钟的时间...


小智 5

1到100.000之间的数字序列:

SELECT e*10000+d*1000+c*100+b*10+a n FROM
(select 0 a 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) t1,
(select 0 b 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) t2,
(select 0 c 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) t3,
(select 0 d 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) t4,
(select 0 e 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) t5
order by 1
Run Code Online (Sandbox Code Playgroud)

我用它来检查某些数字是否不正确,例如:

select * from (
    select 121 id
    union all select 123
    union all select 125
    union all select 126
    union all select 127
    union all select 128
    union all select 129
) a
right join (
    SELECT e*10000+d*1000+c*100+b*10+a n FROM
    (select 0 a 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) t1,
    (select 0 b 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) t2,
    (select 0 c 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) t3,
    (select 0 d 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) t4,
    (select 0 e 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) t5
    order by 1
) seq on seq.n=a.id
where seq.n between 121 and 129
and   id is null
Run Code Online (Sandbox Code Playgroud)

结果将是121和129之间的序列数122和124的间隔:

id     n
----   ---
null   122
null   124
Run Code Online (Sandbox Code Playgroud)

也许它可以帮助某人!


sim*_*eco 5

最简单的方法是:

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

或在一个查询中:

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

FLOOR()此处使用该函数来获取 anINTEGER代替 a FLOAT。有时是需要的。

我的回答受到David Poor 回答的启发。谢谢大卫!


Max*_*rov 5

计数器从 1 到 1000:

  • 无需创建表
  • 执行时间 ~ 0.0014 秒
  • 可以转换成视图
    select tt.row from
    (
    SELECT cast( concat(t.0,t2.0,t3.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
Run Code Online (Sandbox Code Playgroud)

学分:答案,赛斯·麦考利在答案下方的评论。