有没有办法生成可以在JOIN中使用的任意数量的行,类似于Oracle语法:
SELECT LEVEL FROM DUAL CONNECT BY LEVEL<=10
答案 0 :(得分:25)
讨厌这样说,但是MySQL
是四大中唯一没有此功能的RDBMS
。
在Oracle
:
SELECT *
FROM dual
CONNECT BY
level < n
在MS SQL
(最多100
行)中:
WITH hier(row) AS
(
SELECT 1
UNION ALL
SELECT row + 1
FROM hier
WHERE row < n
)
SELECT *
FROM hier
或使用提示到32768
WITH hier(row) AS
(
SELECT 1
UNION ALL
SELECT row + 1
FROM hier
WHERE row < 32768
)
SELECT *
FROM hier
OPTION (MAXRECURSION 32767) -- 32767 is the maximum value of the hint
在PostgreSQL
:
SELECT *
FROM generate_series (1, n)
在MySQL
中,没有。
答案 1 :(得分:13)
在MySql中,我理解你可以使用没有表(或DUAL)的SELECT获得多行。
因此,要获取多行,您执行需要一个至少包含所需行数的实际或临时表。
但是,您不需要构建临时表,因为您可以使用 ANY 现有表,该表至少具有所需的行数。因此,如果您的表格至少包含所需的行数,请使用:
SELECT @curRow := @curRow + 1 AS row_number
FROM sometable
JOIN (SELECT @curRow := 0) r
WHERE @curRow<100;
只需将“sometable”替换为您的任何表的名称,并至少包含所需的行数。
PS:“r”是表“别名”:我本可以使用“AS r”。 FROM或JOIN子句中的任何子查询都会创建一个“派生表”,与所有表一样,它必须具有名称或别名。 (参见MySql手册:13.2.9.8.FOM子句中的子查询)
答案 2 :(得分:3)
由于这是Google目前“mysql行生成器”的第一个结果,我将添加更新。
如果您的MySQL风味恰好是MariaDB,他们就有这个功能。它被称为"Sequence Storage engine",它的用法如下:
select * from seq_1_to_10;
结果:
+-----+
| seq |
+-----+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
+-----+
10 rows in set (0.00 sec)
在版本10.0之前,它是一个需要显式安装的独立插件,但从10.0开始它内置。享受!
答案 3 :(得分:2)
我有一个包含数字x的列(c5
)的表,我需要一个重复相同行x次的SQL表达式。
我的表A包含:
c1 c2 c3 c4 c5
16 1 2 16 3
16 1 2 17 2
16 1 2 18 1
我需要:
c1 c2 c3 c4 c5 n
16 1 2 16 3 1
16 1 2 16 3 2
16 1 2 16 3 3
16 1 2 17 2 1
16 1 2 17 2 2
16 1 2 18 1 1
我用表达式解决了这个问题:
SELECT
c1, c2, c3, c4, c5, row_number AS n
FROM
(
SELECT
@curRow := @curRow + 1 AS row_number
FROM
tablea
JOIN (SELECT @curRow := 0) r
WHERE
@curRow < (
SELECT
max(field1)
FROM
tablea
)
) AS vwtable2
LEFT JOIN tablea d ON vwtable2.row_number <= tablea.field1;
答案 4 :(得分:2)
对于MySQL 8.0,MariaDB 10.2和更高版本,您可以使用递归CTE:
WITH RECURSIVE sequence AS (
SELECT 1 AS level
UNION ALL
SELECT level + 1 AS value
FROM sequence
WHERE sequence.level < 10
)
SELECT level
FROM sequence;
请注意,在MySQL中,CTE受cte_max_recursion_depth
(默认为1000,最大为4,294,967,295(2³²−1))的限制,而在MariaDB中,受max_recursive_iterations
(默认为4,294,967,295)的限制。
您可以通过执行以下操作来增加限制:
SET cte_max_recursion_depth = 4294967295;
这只会影响您当前的会话,并且不会持续。
对于8.0之前的MySQL版本,您可以使用以下Markus Winand的巧妙技巧:
CREATE OR REPLACE VIEW generator_16
AS SELECT 0 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 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL
SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL
SELECT 15;
CREATE OR REPLACE VIEW generator_256
AS SELECT ( ( hi.n << 4 ) | lo.n ) AS n
FROM generator_16 lo, generator_16 hi;
CREATE OR REPLACE VIEW generator_4k
AS SELECT ( ( hi.n << 8 ) | lo.n ) AS n
FROM generator_256 lo, generator_16 hi;
CREATE OR REPLACE VIEW generator_64k
AS SELECT ( ( hi.n << 8 ) | lo.n ) AS n
FROM generator_256 lo, generator_256 hi;
CREATE OR REPLACE VIEW generator_1m
AS SELECT ( ( hi.n << 16 ) | lo.n ) AS n
FROM generator_64k lo, generator_16 hi;
CREATE OR REPLACE VIEW generator_16m
AS SELECT ( ( hi.n << 16 ) | lo.n ) AS n
FROM generator_64k lo, generator_256 hi;
CREATE OR REPLACE VIEW generator_4b
AS SELECT ( ( hi.n << 16 ) | lo.n ) AS n
FROM generator_64k lo, generator_64k hi;
然后:
SELECT n FROM generator_4b limit 10;
在我的笔记本电脑上,创建generator_4b
只需花费约20毫秒,其中{
"compilerOptions": {
"target": "es2017",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
},
"include": [
"src"
],
}
包含40亿行。而且上述所有生成器视图的总存储空间仅为28 KB。
如果您想知道它是如何工作的,可以在他的blog post中找到详细的说明。
答案 5 :(得分:1)
如果我理解你,你想要一个连续数字列表?
只需列出清单:
create table artificial_range (id int not null primary key auto_increment, idn int);
insert into artificial_range (idn) values (0); --first row
insert into artificial_range(idn) select idn from artificial_range; --2nd
insert into artificial_range(idn) select idn from artificial_range; -- now 4 rows
insert into artificial_range(idn) select idn from artificial_range; --8
insert into artificial_range(idn) select idn from artificial_range; --16
insert into artificial_range(idn) select idn from artificial_range; --32
insert into artificial_range(idn) select idn from artificial_range; --64
insert into artificial_range(idn) select idn from artificial_range; --128
......等等,直到你有1024。
update artificial_range set idn = id - 1 ;
- 现在你有一个系列盯着1(id)和一个从0开始的系列
现在加入它,或加入它的转换:
create view days_this_century as
select date_add('2000-01-01', interval a.idn day) as cdate
from artificial_range;
答案 6 :(得分:0)
我不知道这是否有帮助,但您可以使用sth对每个select语句中的行进行编号。像:
SET @NUM = 0;
SELECT @NUM:= @ NUM + 1 rowNumber,* FROM ...
然后加入他们。 在大型数据库中,这可能非常慢。
答案 7 :(得分:0)
要生成10行:
SELECT a AS 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 from dual
您可以生成100行并与另外10行进行连接:
select t2.a*10 + t1.a from
(SELECT 0 AS 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 AS 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) t2
然后再添加1000行并添加另一个连接...
答案 8 :(得分:0)
可以,但是有点棘手,
在这里:
mysql> create table t(inc bigint primary key auto_increment);
Query OK, 0 rows affected (0.03 sec)
mysql> insert into t values(0);
Query OK, 1 row affected (0.01 sec)
mysql> insert into t select 0 from t;
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> insert into t select 0 from t;
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> insert into t select 0 from t;
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> insert into t select 0 from t;
Query OK, 8 rows affected (0.01 sec)
Records: 8 Duplicates: 0 Warnings: 0
mysql> select count(inc), max(inc) from t;
+------------+----------+
| count(inc) | max(inc) |
+------------+----------+
| 16 | 20 |
+------------+----------+
1 row in set (0.00 sec)
mysql> select row_number() over w as inc from t window w as (order by inc);
+-----+
| inc |
+-----+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
| 11 |
| 12 |
| 13 |
| 14 |
| 15 |
| 16 |
+-----+
16 rows in set (0.00 sec)
您可以通过发出以下语句来使生成的行数加倍
insert into t select 0 from t;
根据需要。
还要注意,默认情况下 auto_increment 会产生一些间隙,这就是使用 row_number()的原因。