SQL SELECT获取前N个正整数

时间:2009-09-25 07:53:25

标签: sql mysql

我需要得到一个包含前N个正整数的结果集。是否可以仅使用标准SQL SELECT语句来获取它们(不提供任何计数表)?

如果不可能,是否有任何特定的MySQL方法来实现这一目标?

10 个答案:

答案 0 :(得分:16)

似乎你想要的是dummy rowset

MySQL中,没有桌子就不可能。

大多数主要系统提供了一种方法:

  • Oracle

    SELECT  level
    FROM    dual
    CONNECT BY
            level <= 10
    
  • SQL Server

    WITH    q AS
            (
            SELECT  1 AS num
            UNION ALL
            SELECT  num + 1
            FROM    q
            WHERE   num < 10
            )
    SELECT  *
    FROM    q
    
  • PostgreSQL

    SELECT  num
    FROM    generate_series(1, 10) num
    

MySQL缺少类似的东西,这是一个严重的缺点。

我写了一个简单的脚本来为我的博客文章中的示例表生成测试数据,也许它会有用:

CREATE TABLE filler (
        id INT NOT NULL PRIMARY KEY AUTO_INCREMENT
) ENGINE=Memory;

CREATE PROCEDURE prc_filler(cnt INT)
BEGIN
        DECLARE _cnt INT;
        SET _cnt = 1;
        WHILE _cnt <= cnt DO
                INSERT
                INTO    filler
                SELECT  _cnt;
                SET _cnt = _cnt + 1;
        END WHILE;
END
$$

你打电话给程序,表格里面都填满了数字。

您可以在会话期间重复使用它。

答案 1 :(得分:10)

一种可能的解决方案(当然不是很优雅)是使用任何具有足够大量记录的表。

对于前10个整数(使用mysql.help_relation,但任何表都可以),您可以使用以下查询:

SELECT  @N := @N +1 AS integers 
FROM mysql.help_relation , (SELECT @N:=0) dum LIMIT 10;

这也可以放在Min和Max的函数中。

答案 2 :(得分:4)

奇怪的解决方案,但是......

SELECT 1 UNION SELECT 2 UNION SELECT 3....

答案 3 :(得分:4)

我建议的序列允许程序员执行以下查询:

select value from sequence where value>=15 and value<100;

并获得预期的结果:15(包括)和100(不包括)之间的整数序列。

如果这是您想要的,您将必须创建以下两个视图,您只需声明一次的视图:

create view digits as select 0 n 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;

create view sequence as select u.n+t.n*10+h.n*100 as value from digits as u cross join digits as t cross join digits as h;

通过这种方式,您可以使用直观的SELECT ...

希望它有所帮助。

答案 4 :(得分:2)

假设你的意思是从表中检索它们,这里N是10,假设intcolumn是包含数字的列。

SELECT intcolumn FROM numbers WHERE intcolumn > 0 LIMIT 10

编辑:如果您实际上想要获得没有表格的正数数学集合,我会重新考虑,它可能是密集的(取决于实现)。通常接受的做法似乎是创建一个包含数字的查找表,然后使用上面的查询。

答案 5 :(得分:1)

这可能会有所帮助

获得i <= R <1的范围内的随机整数R. j,使用表达式FLOOR(i + RAND()*(j-i))。例如,为了获得范围7 <= R <1的范围内的随机整数。 12,您可以使用以下语句:

SELECT FLOOR(7 + (RAND() * 5));

答案 6 :(得分:1)

如果你知道N是有限的(通常是),你可以使用如下结构:

select (a.digit + (10 * b.digit) + (100 * c.digit) + (1000 * d.digit) + (10000 * e.digit) + (100000 * f.digit)) as n
    from (select 0 as digit 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) as a
    cross join (select 0 as digit 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) as b
    cross join (select 0 as digit 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) as c
    cross join (select 0 as digit 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) as d
    cross join (select 0 as digit 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) as e
    cross join (select 0 as digit 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) as f;

将产生第一百万个数字。如果您只需要正数,只需将+ 1添加到表达式。

请注意,特别是在MySQL中,结果可能无法排序。如果您需要订购号码,则需要将order by n追加到最后。这会大大增加执行时间,但是(在我的机器上,它从5毫秒跳到500毫秒)。

对于简单查询,这里只查询前10000个数字:

select (a.digit + (10 * b.digit) + (100 * c.digit) + (1000 * d.digit)) as n
    from (select 0 as digit 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) as a
    cross join (select 0 as digit 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) as b
    cross join (select 0 as digit 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) as c
    cross join (select 0 as digit 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) as d;

此答案改编自以下返回日期范围的查询:https://stackoverflow.com/a/2157776/2948

答案 7 :(得分:0)

看看以下SO问题:

修改

另一个方法是创建一个为您执行此操作的存储过程。 PostgreSQL包含一个函数generate_series(start,stop),可以完成你想要的任务。

select * from generate_series(2,4);
 generate_series
-----------------
               2
               3
               4
(3 rows)

我不熟悉MySQL,但如果你对SP没问题,那么这样的事情应该很容易实现。 This网站显示了一个实现。

答案 8 :(得分:0)

如果我理解你的问题,我很确定你不能这样做。

据我所知,您需要从单个SQL语句中获取列表,而不必引用特定的表吗?

我很确定在任何SQL方言中都不可能。如果你得到一个顺序递增的数字以及另一个查询的结果,那么这是可能的(取决于SQL方言,在mssql上它将是rownumber(),但我不知道如何在MySql中,但它可能有)

但那不是我听到你问的那个?

答案 9 :(得分:0)

如果您的数据库支持分析窗口函数,则以下操作非常简单:

SELECT  row_number() over (partition by 1 order by 1) numbers
FROM SOME_TABLE
LIMIT 2700;

此语句返回1到2700之间的一组数字。