如何在MySQL中创建行生成器?

Gam*_*eak 21 mysql sql generator

有没有办法生成可以在JOIN中使用的任意数量的行,类似于Oracle语法:

SELECT LEVEL FROM DUAL CONNECT BY LEVEL<=10
Run Code Online (Sandbox Code Playgroud)

Qua*_*noi 25

讨厌这样说,但是没有这个功能的四巨头中MySQL唯一RDBMS.

Oracle:

SELECT  *
FROM    dual
CONNECT BY
        level < n
Run Code Online (Sandbox Code Playgroud)

MS SQL(最多100行):

WITH hier(row) AS
        (
        SELECT  1
        UNION ALL
        SELECT  row + 1
        FROM    hier
        WHERE   row < n
        )
SELECT  *
FROM    hier
Run Code Online (Sandbox Code Playgroud)

或使用提示 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
Run Code Online (Sandbox Code Playgroud)

PostgreSQL:

SELECT  *
FROM    generate_series (1, n)
Run Code Online (Sandbox Code Playgroud)

MySQL,什么都没有.

  • Reg MySQL:希望能填补这一空白:http://use-the-index-luke.com/blog/2011-07-30/mysql-row-generator#mysql_generator_code (4认同)

DrD*_*ave 13

在MySql中,我理解你可以使用没有表(或DUAL)的SELECT获得多行.

因此,为了得到多行,你需要至少所需的行数的真实的或临时表.

但是,您不需要构建临时表,因为您可以使用至少具有所需行数的任何现有表.因此,如果您的表至少具有所需的行数,请使用:

SELECT  @curRow := @curRow + 1 AS row_number
FROM    sometable 
JOIN    (SELECT @curRow := 0) r
WHERE   @curRow<100;
Run Code Online (Sandbox Code Playgroud)

只需将"sometable"替换为您的任何表的名称,并至少包含所需的行数.

PS:"r"是表"别名":我本可以使用"AS r".FROM或JOIN子句中的任何子查询都会创建一个"派生表",与所有表一样,它必须具有名称或别名.(参见MySql手册:13.2.9.8.FOM子句中的子查询)


Den*_*huk 8

MySQL 8.0

在 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;
Run Code Online (Sandbox Code Playgroud)

请注意,CTEcte_max_recursion_depth在 MySQL 中受到(默认 1000,最大 4,294,967,295 (2³²?1))和max_recursive_iterationsMariaDB 中(默认为 4,294,967,295)的限制。

您可以通过执行以下操作来增加限制:

SET cte_max_recursion_depth = 4294967295;
Run Code Online (Sandbox Code Playgroud)

它只会影响您当前的会话,不会持久化。

MySQL 5.7、5.6 及以下

对于 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;
Run Code Online (Sandbox Code Playgroud)

进而:

SELECT n FROM generator_4b limit 10;
Run Code Online (Sandbox Code Playgroud)

在我的笔记本电脑上创建 even 只需要大约 20 毫秒generator_4b,其中包含超过 40 亿行。上面所有的生成器视图组合起来只占用 28 KB 的存储空间。

如果你想知道它是如何工作的,你可以在他的博客文章中找到详细的解释。


Vil*_*lx- 5

由于这是Google目前“ mysql row generator”的首批结果之一,因此我将添加一个更新。

如果您的MySQL碰巧是MariaDB,则它们具有此功能。它被称为“序列存储引擎”,其用法如下:

select * from seq_1_to_10;
Run Code Online (Sandbox Code Playgroud)

结果:

+-----+
| seq |
+-----+
|   1 |
|   2 |
|   3 |
|   4 |
|   5 |
|   6 |
|   7 |
|   8 |
|   9 |
|  10 |
+-----+
10 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

在10.0版之前,它是一个单独的插件,需要明确安装,但是从10.0版开始,它是内置的。