我需要与一个包含整数n
到m
(包括n和m)的表/结果集进行连接。是否有一种简单的方法可以避免手动构建该表?
(顺便问一下,这种类型的结构被称为"元查询"吗?)
m-n
的值被限制在合理范围内(小于1000)。
我需要与一个包含整数n
到m
(包括n和m)的表/结果集进行连接。是否有一种简单的方法可以避免手动构建该表?
(顺便问一下,这种类型的结构被称为"元查询"吗?)
m-n
的值被限制在合理范围内(小于1000)。
SET @row := 0;
SELECT @row := @row + 1 as row, t.*
FROM some_table t, (SELECT @row := 0) r
单个查询,快速,并且完全符合我的要求:现在我可以使用唯一数字从1开始对复杂查询中找到的“选择”进行编号,并且每一行结果都会递增一次。
我认为这也适用于上面列出的问题:调整@row
的初始起始值并添加限制子句以设置最大值。
顺便说一下:我认为“r”实际上并不需要。
ddsp
some_table
而不是 r。如果 some_table
没有任何行,则什么都不会返回。我使用这个方法生成了一组测试数据,只需要用户名和密码。序列号变成了用户名,密码只是 ENCRYPT('passwd'),以便它们都相同。为了生成行,我从另一个表中进行选择,但实际上并没有选择任何列。它只是给我每个在 some_table
中的行都提供了一个行,所有行都具有连续的数字。 - MnebuerquoSET @row := 0
和 UPDATE foo SET position = (@row := @row + 1) WHERE <条件> ORDER BY last_modified ASC
。请注意,我的翻译可能不是字面上的翻译,但它们保留了原始内容的含义,并尽力使其更加易懂。 - IzkataSELECT @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;
@row := @row + 1 as row
是必要的,以获得每行递增的数字。联合只是乘以给出行数的数字。 - skbSELECT
添加一个别名即可轻松解决 - 例如,在最后添加t5
。 - Steve Chambers如果您正在使用MySQL的MariaDB分支,则SEQUENCE
引擎允许直接生成数字序列。它通过使用虚拟(假)单列表来实现这一点。
例如,要生成从1到1000的整数序列,请执行以下操作:
SELECT seq FROM seq_1_to_1000;
从0到11,执行此操作。
SELECT seq FROM seq_0_to_11;
从今天开始连续一周的日期值,请执行此操作。
SELECT FROM_DAYS(seq + TO_DAYS(CURDATE)) dateseq FROM seq_0_to_6
针对从“2010-01-01”开始的一连串为时十年的DATE
值,执行以下操作。
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
如果你还没有使用MariaDB,请考虑一下。尝试这个...它在我的mysql 8.0版本中有效。 您可以根据需要修改以下查询范围
尝试此方法...对我来说在mysql 8.0版本中有效。 您可以根据需要修改以下查询。
WITH recursive numbers AS (
select 0 as Date
union all
select Date + 1
from numbers
where Date < 10)
select * from numbers;
是的,不需要像您帖子中提到的那样创建表格。
cte_max_recursion_depth
的默认值。 - saintlyzeroMySQL中没有序列号生成器(CREATE SEQUENCE)。最接近的是AUTO_INCREMENT
,它可以帮助你构建表格。
1到100000之间的数字序列:
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
我使用它来审计是否有一些数字顺序不对,就像这样:
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
id n
---- ---
null 122
null 124
有一种方法可以在单个查询中获取一系列值,但速度较慢。可以通过使用缓存表来加速。
假设您想要选择所有布尔值的范围:
SELECT 0 as b UNION SELECT 1 as b;
CREATE VIEW ViewBoolean AS SELECT 0 as b UNION SELECT 1 as b;
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;
CREATE VIEW ViewInt16 AS
SELECT b0.v + b1.v*256 as v FROM
ViewByteValues b0,ViewByteValues b1;
SELECT v+MIN as x FROM ViewInt16 WHERE v<MAX-MIN;
CREATE VIEW ViewByteValues AS
SELECT 0 as v UNION SELECT 1 as v UNION SELECT ...
...
...254 as v UNION SELECT 255 as v;
SELECT DATE_ADD('start_date',v) as day FROM ViewInt16 WHERE v<NumDays;
或者
SELECT DATE_ADD('start_date',v) as day FROM ViewInt16 WHERE day<'end_date';
你可以通过稍微更快的MAKEDATE函数来加速此过程。
SELECT MAKEDATE(start_year,1+v) as day FRON ViewInt16 WHERE day>'start_date' AND day<'end_date';
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;
我会将您的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);
只要你用LIMIT 1,30或类似的方式限制结果,即使MAX-MIN很大,查询速度也会相对较快。但是,使用COUNT(*)将需要很长时间。如果在MAX-MIN大于100k时添加ORDER BY,计算时间将再次延长数秒...
计数器从1到1000:
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
来源: 回答,Seth McCauley在回答下方的评论。
您可以尝试像这样做:
SELECT @rn:=@rn+1 as n
FROM (select @rn:=2)t, `order` rows_1, `order` rows_2 --, rows_n as needed...
LIMIT 4
这里的order
只是一个有相当多行的表格的例子。
编辑:原回答是错误的,任何功劳应归于David Poor,他提供了同样概念的工作示例。
order
进行笛卡尔积意味着该变量将与从2到订单数+2的数字序列相关联(限制4将其限制为4个数字)。 - John Nilssonorder
,其中包含可能匹配的整数的完整列表。如果我尝试不加入到一个已经存在有效整数的大型预先存在的表中运行,我将无法得到除单行结果之外的任何内容。 - rektideSET @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()
函数,将 FLOAT
转换为 INTEGER
。有时候这是必需的。