【问题标题】:How to select a single row a 100 million x如何选择单行一亿个x
【发布时间】:2011-11-22 18:16:27
【问题描述】:

我想使用选择中的单行生成以下输出。

SELECT max(t1.id)+1 as new_id FROM t1;
-> 101

However I want to do

SELECT s.last_id, sequence(1..100000000) as new_id 
FROM (SELECT max(table1.id)+1 as last_id FROM table1) s;
-> 101,1
-> 101,2
-> 101,3 
......
-> 101,100000000

在 postgreSQL 中我可以使用:

SELECT s.last_id, generate_series(1,100000000) 
FROM (SELECT max(table1.id)+1 as last_id FROM table1) s;  -- returns 100,000,000 rows 

如何在 MySQL 中做到这一点而不使用临时表?

【问题讨论】:

  • 派生表呢?我们也可以假设存在一个至少有 100 行的任意表吗?
  • @MartinSmith,聪明,我更喜欢没有这种假设的解决方案,所以所有表都只有 1 行。
  • @Johan:如果你所有的表都有 1 行,你就不需要数据库,是吗?
  • @ypercube,我用trick 标记它,因为我需要使用这个技巧来快速填充随机数据的数据库。你要我写一亿行吗?
  • 我只是在逗你。但是,是的,提到你希望它用于非常大的序列,会很好。

标签: mysql


【解决方案1】:

感谢@harper89,我在这里找到了答案:

http://use-the-index-luke.com/blog/2011-07-30/mysql-row-generator#mysql_generator_code

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 
     CROSS JOIN generator_16 hi;

CREATE OR REPLACE VIEW generator_4k
AS SELECT ( ( hi.n << 8 ) | lo.n ) AS n
     FROM generator_256 lo
     CROSS JOIN generator_16 hi;

CREATE OR REPLACE VIEW generator_64k
AS SELECT ( ( hi.n << 8 ) | lo.n ) AS n
     FROM generator_256 lo
     CROSS JOIN generator_256 hi;

CREATE OR REPLACE VIEW generator_1m
AS SELECT ( ( hi.n << 16 ) | lo.n ) AS n
     FROM generator_64k lo
     CROSS JOIN generator_16 hi;

现在我可以生成我想要的结果了:

SELECT s.last_id, g.n as new_id FROM (SELECT max(table1.id)+1 as last_id FROM table1) s
CROSS JOIN generator_256 g
WHERE G.N BETWEEN 1 AND 100
ORDER BY g.n ASC;

使用LIMIT 是个坏主意,因为临时表中将存储多达一百万多行。使用where,您不需要临时存储。

【讨论】:

  • 啊,我在感叹 MySQL 中缺乏 CTE,但当然您可以使用对 MySQL 不够熟悉的视图 (+1) 来了解 LIMIT 的缺点!
  • @MartinSmith,Limit 的工作原理是选择所有行,将这些行存储在临时表中(在磁盘上或内存中),然后只提供前 x 行。
  • 好吧,我的第二个版本也不需要。顺便说一句,每个正整数都是一些 2 的幂的总和,所以也许你可以为每个 2 的幂创建视图,直到某个数字然后交叉加入一个联合,所有这些加起来都是正确的数字?还是会在 MySQL 中具体化为一些中间结果集?
【解决方案2】:

对布鲁诺的解决方案稍作修改

SELECT (SELECT COALESCE(max(id),0)+1 FROM table1), 
        @rownum:=@rownum+1 new_id 
FROM 
(SELECT @rownum:=0) r, 
(SELECT 1 UNION ALL SELECT 2) t1,
(SELECT 1 UNION ALL SELECT 2) t2,
(SELECT 1 UNION ALL SELECT 2) t3,
(SELECT 1 UNION ALL SELECT 2) t4,
(SELECT 1 UNION ALL SELECT 2) t5,
(SELECT 1 UNION ALL SELECT 2) t6,
(SELECT 1 UNION ALL SELECT 2) t7
LIMIT 100

或者没有变量的另一个版本

SELECT (SELECT Coalesce(MAX(id), 0) + 1
        FROM   table1),
       t1.n * 10 + t2.n + 1 AS new_id
FROM   (SELECT 0 AS 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) t1,
       (SELECT 0 AS 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) t2
ORDER  BY new_id  

【讨论】:

  • 我认为如果您将limit 替换为where,它会运行得更快。很好的答案,因为您不需要预先创建数字生成器。
  • 问一个问题,如果可以的话,我可以将其扩展到 100,000,000 行吗?
  • @Johan - 您可以将其粘贴到视图中并多次交叉连接。如果您在单独的视图中执行了多个交叉连接技巧,那么1010010,000 只需要 3 个视图,然后在最后一个交叉连接上得到 100,000,000
【解决方案3】:

MYSql 中没有任何东西等于generate_series。在阅读下面的链接之后,似乎除了 MySQL 之外 SQL 所做的一切。

确认Here

看来您将不得不采取更复杂的路线,但我没有足够的经验来给出答案,那里的链接和答案可能会引导您走向正确的方向。

旁注:

您可以使用 LIMIT 100 仅返回 100 行,但您似乎想要一些稍微不同的东西。

【讨论】:

  • +1,那个链接是金色的。解决方案在文章底部。
  • 太棒了,我不确定我只知道生成不是一个选项。享受吧!
【解决方案4】:

约翰,

你使用这个表格:

SELECT max(t1.id)+1, @rownum:=@rownum+1 rownum
FROM (SELECT @rownum:=0) r, t1;

测试这个sql,我认为代码已经解析了。

【讨论】:

  • 您缺少 LIMITmax(t1.id)+1 无论如何只会返回 1 行,因此您需要以某种方式扩展此结果。
  • 您正在对两个结果集进行交叉连接,每个结果集只有一行。那只会生成 1 行。我觉得你正朝着正确的方向前进,但事实并非如此。
猜你喜欢
  • 2013-11-18
  • 2010-11-02
  • 1970-01-01
  • 2017-07-12
  • 2021-02-16
  • 2020-01-21
  • 1970-01-01
  • 2011-02-18
  • 1970-01-01
相关资源
最近更新 更多