I need to do a join with a table/result-set/whatever that has the integers n to m inclusive. Is there a trivial way to get that without just building the table?
我需要与包含n到m的整数的表/结果集/任何东西进行连接。是否有一种不需要构建表格就能实现的简单方法?
(BTW what would that type of construct be called, a "Meta query"?)
(顺便问一下,这种类型的结构会被称为“元查询”吗?)
m-n is bounded to something reasonable ( <1000's)
m-n有一个合理的值(<1000)
6
There is no sequence number generator (CREATE SEQUENCE) in MySQL. Closest thing is AUTO_INCREMENT
, which can help you construct the table.
MySQL中没有序列号生成器(创建序列号)。最接近的是AUTO_INCREMENT,它可以帮助您构建表。
86
I found this solution on the web
我在网上找到了这个解决方案
SELECT @row := @row + 1 as row, t.*
FROM some_table t, (SELECT @row := 0) r
Single query, fast, and does exactly what I wanted: now I can "number" the "selections" found from a complex query with unique numbers starting at 1 and incrementing once for each row in the result.
单查询,速度很快,并且完成了我想要的:现在我可以对从复杂查询中找到的“选择”进行“编号”,从1开始,对结果中的每一行进行一次递增。
I think this will also work for the issue listed above: adjust the initial starting value for @row
and add a limit clause to set the maximum.
我认为这也适用于上面列出的问题:调整@row的初始值,并添加一个limit子句来设置最大值。
BTW: I think that the "r" is not really needed.
顺便说一句,我认为“r”不是真的需要。
ddsp
ddsp
29
The following will return 1..10000 and is not so slow
下面将返回1..10000并不是那么慢
SELECT @row := @row + 1 as row FROM
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 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 3 union all select 4 union all select 5 union all select 6 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 3 union all select 4 union all select 5 union all select 6 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 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t4,
(SELECT @row:=0)
14
If you happen to be using the MariaDB fork of MySQL, the SEQUENCE
engine allows direct generation of number sequences. It does this by using virtual (fake) one column tables.
如果您碰巧使用的是MySQL的MariaDB fork,那么序列引擎可以直接生成数字序列。它通过使用虚拟(假)一个列表来实现这一点。
For example, to generate the sequence of integers from 1 to 1000, do this
例如,要生成从1到1000的整数序列,请这样做
SELECT seq FROM seq_1_to_1000;
For 0 to 11, do this.
从0到11,做这个。
SELECT seq FROM seq_0_to_11;
For a week's worth of consecutive DATE values starting today, do this.
对于从今天开始连续一周的日期值,请这样做。
SELECT FROM_DAYS(seq + TO_DAYS(CURDATE)) dateseq FROM seq_0_to_6
For a decade's worth of consecutive DATE
values starting with '2010-01-01' do this.
以“2010-01-01”开头的10年连续日期值可以这样做。
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
If you don't happen to be using MariaDB, please consider it.
如果您没有使用MariaDB,请考虑它。
5
You could try something like this:
你可以试试这样的方法:
SELECT @rn:=@rn+1 as n
FROM (select @rn:=2)t, `order` rows_1, `order` rows_2 --, rows_n as needed...
LIMIT 4
Where order
is just en example of some table with a reasonably large set of rows.
其中,order只是某个表的一个例子,该表具有相当大的行集。
Edit: The original answer was wrong, and any credit should go to David Poor who provided a working example of the same concept
编辑:最初的答案是错误的,任何功劳都应该归于大卫·普尔,他提供了一个相同概念的工作示例
3
There is a way to get a range of values in a single query, but its a bit slow. It can be sped up by using cache tables.
有一种方法可以在单个查询中获取一系列值,但这有点慢。它可以通过使用缓存表来加速。
assume you want a select with a range of all BOOLEAN values:
假设您想要一个具有所有布尔值范围的选择:
SELECT 0 as b UNION SELECT 1 as b;
we can make a view
我们可以看一下。
CREATE VIEW ViewBoolean AS SELECT 0 as b UNION SELECT 1 as b;
then you can do a Byte by
然后你可以做一个字节by
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;
then you can do a
然后你可以做a
CREATE VIEW ViewInt16 AS
SELECT b0.v + b1.v*256 as v FROM
ViewByteValues b0,ViewByteValues b1;
then you can do a
然后你可以做a
SELECT v+MIN as x FROM ViewInt16 WHERE v
To speed this up I skipped the auto-calculation of byte values and made myself a
为了加快速度,我跳过了字节值的自动计算,把自己变成了a
CREATE VIEW ViewByteValues AS
SELECT 0 as v UNION SELECT 1 as v UNION SELECT ...
...
...254 as v UNION SELECT 255 as v;
If you need a range of dates you can do.
如果你需要一系列的约会,你可以这么做。
SELECT DATE_ADD('start_date',v) as day FROM ViewInt16 WHERE v
or
或
SELECT DATE_ADD('start_date',v) as day FROM ViewInt16 WHERE day<'end_date';
you might be able to speed this up with the slightly faster MAKEDATE function
您可以使用更快的MAKEDATE函数来加快速度
SELECT MAKEDATE(start_year,1+v) as day FRON ViewInt16 WHERE day>'start_date' AND day<'end_date';
Please note that this tricks are VERY SLOW and only allow the creation of FINITE sequences in a pre-defined domain (for example int16 = 0...65536 )
请注意,这个技巧非常慢,并且只允许在预定义的域中创建有限的序列(例如,int16 = 0……)65536)
I am sure you can modify the queries a bit to speed things up by hinting to MySQL where to stop calculating ;) (using ON clauses instead of WHERE clauses and stuff like that)
我相信您可以稍微修改一下查询,通过提示MySQL停止计算;)(使用ON子句而不是where子句之类的东西)
For example:
例如:
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)
will keep your SQL server busy for a few hours
SQL服务器会忙上几个小时吗
However
然而
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);
will run reasonably fast - even if MAX-MIN is huge as long as you limit the result with LIMIT 1,30 or something. a COUNT(*) however will take ages and if you make the mistake of adding ORDER BY when MAX-MIN is bigger than say 100k it will again take several seconds to calculate...
将运行得相当快——即使是MAX-MIN是巨大的,只要你把结果限制在1、30或其他东西。但是,计数(*)需要花费很长时间,如果您犯了这样的错误:当MAX-MIN大于100k时,您将再次花费数秒来计算……
2
How big is m?
米有多大?
You could do something like:
你可以这样做:
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;
where the auto_increment is set to n and the where clause compares to m and the number of times the two table is repeated is at least ceil(log(m-n+1)/log(2)).
其中auto_increment设置为n, where子句比较m,且两个表重复的次数至少为ceil(log(m-n+1)/log(2))。
(The non-temporary two table could be omitted by replacing two with (select null foo union all select null) in the create temporary table seq.)
(在创建临时表seq中,替换两个with(选择null foo union all select null)可以省略非临时的两个表。)
2
Sequence of numbers between 1 and 100.000:
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
I use it to audit if some number is out of sequence, something like this:
我用它来审计如果某个数字不符合顺序,像这样:
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
The result will be the gap of number 122 and 124 of sequence between 121 and 129:
结果将是第122和第124号序列在121和129之间的间隙:
id n
---- ---
null 122
null 124
Maybe it helps someone!
也许它能帮助一些人!
1
You appear to be able to construct reasonably large sets with:
你似乎能够构造相当大的集合,包括:
select 9 union all select 10 union all select 11 union all select 12 union all select 13 ...
I got a parser stack overflow in the 5300's, on 5.0.51a.
我得到了一个解析器堆栈溢出在5300,在5.0.51a。
1
Warning: if you insert numbers one row at a time, you'll end up executing N commands where N is the number of rows you need to insert.
警告:如果您一次插入一行数字,那么您将会执行N个命令,其中N是需要插入的行数。
You can get this down to O(log N) by using a temporary table (see below for inserting numbers from 10000 to 10699):
您可以通过使用临时表(参见下面关于从10000到10699插入数字的说明)将其降低到O(log N):
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, unfortunately this won't work with a true temporary table with MySQL 5.0 as it can't insert into itself (you could bounce back and forth between two temporary tables).
编辑:fyi,不幸的是,这不能使用一个真正的临时表,因为它不能插入到它本身(您可以在两个临时表之间来回跳转)。
edit: You could use a MEMORY storage engine to prevent this from actually being a drain on the "real" database. I wonder if someone has developed a "NUMBERS" virtual storage engine to instantiate virtual storage to create sequences such as this. (alas, nonportable outside MySQL)
编辑:您可以使用内存存储引擎来防止这实际上成为“真实”数据库的消耗。我想知道是否有人开发了一个“数字”虚拟存储引擎来实例化虚拟存储以创建这样的序列。(唉,移植的MySQL外)
1
Here is a compact binary version of the technique used in other answers here:
这里是一个紧凑的二进制版本的技术,用于其他的答案:
select ((((((b7.0 <<1 | b6.0) <<1 | b5.0) <<1 | b4.0)
<<1 | b3.0) <<1 | b2.0) <<1 | b1.0) <<1 | b0.0 as n
from (select 0 union all select 1) as b0,
(select 0 union all select 1) as b1,
(select 0 union all select 1) as b2,
(select 0 union all select 1) as b3,
(select 0 union all select 1) as b4,
(select 0 union all select 1) as b5,
(select 0 union all select 1) as b6,
(select 0 union all select 1) as b7
There are no unique or sorting phases, no string to number conversion, no arithmetic operations, and each dummy table only has 2 rows, so it should be pretty fast.
没有唯一的或排序的阶段,没有字符串到数字的转换,没有算术运算,每个虚拟表只有2行,所以它应该很快。
This version uses 8 "bits" so it counts from 0 to 255, but you can easily tweak that.
这个版本使用8个“位”,所以从0到255,但是您可以很容易地调整它。
0
If you were using Oracle, 'pipelined functions' would be the way to go. Unfortunately, MySQL has no such construct.
如果您正在使用Oracle,“管道函数”将是一种方法。不幸的是,MySQL没有这样的结构。
Depending on the the scale of the numbers you want sets of, I see two simple ways to go : you either populate a temporary table with just the numbers you need (possibly using memory tables populated by a stored procedure) for a single query or, up front, you build a big table that counts from 1 to 1,000,000 and select bounded regions of it.
根据你想要的数字集的规模,我看到两个简单的方法:你要么填充一个临时表只有你需要的数字(可能使用内存表的存储过程)为一个查询,或者,你构建一个大表,计算从1到1000000,并选择有界区域。
0
This query generates numbers from 0 to 1023. I believe it would work in any sql database flavor:
这个查询生成从0到1023的数字。我相信它可以在任何sql数据库中工作:
select
i0.i
+i1.i*2
+i2.i*4
+i3.i*8
+i4.i*16
+i5.i*32
+i6.i*64
+i7.i*128
+i8.i*256
+i9.i*512
as i
from
(select 0 as i union select 1) as i0
cross join (select 0 as i union select 1) as i1
cross join (select 0 as i union select 1) as i2
cross join (select 0 as i union select 1) as i3
cross join (select 0 as i union select 1) as i4
cross join (select 0 as i union select 1) as i5
cross join (select 0 as i union select 1) as i6
cross join (select 0 as i union select 1) as i7
cross join (select 0 as i union select 1) as i8
cross join (select 0 as i union select 1) as i9