2009-09-25 64 views
12

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

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

+0

首先在什么defintion? – 2009-09-25 07:56:26

回答

15

看来,你想要的是一个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 
$$ 

你调用过程并表被填充数字。

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

+0

很棒的回答。这肯定是有帮助的。 – monn 2009-09-26 19:10:58

2

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

SELECT intcolumn FROM numbers WHERE intcolumn > 0 LIMIT 10 

编辑:如果你实际上是希望得到的数学组正数的不表,我会重新考虑,也可以是密集的(取决于实现)。通常接受的做法似乎是创建一个充满数字的查找表,然后使用上述查询。

+0

只需将> =改为>即可获得肯定结果。 – dusoft 2009-09-25 07:56:42

+0

0被认为是正面还是负面? – rahul 2009-09-25 07:57:13

+0

我刚刚查过,显然正数的定义大于0.显然零不是(根据维基百科)。 – Kazar 2009-09-25 07:58:31

0

在该followhing SO问题请看:

编辑:

另一种形式给出是创建一个存储过程,这是否为你。 PostgreSQL包含一个函数generate_series(start,stop),它可以做你想做的事情。

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

我不熟悉MySQL,但是像这样的东西应该很容易实现,如果你对SP好的话。 This网站显示一个实施。

+0

看起来好像这两种方法都需要某种形式的查找表(使用AUTO_INCREMENT) – Kazar 2009-09-25 08:07:43

0

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

正如我理解你的问题,你想从单个SQL语句的列表,而不必引用特定的表?

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

但是,这不是我听到你问?

+0

在PostgreSQL中有一个名为generate_series(start,stop)的函数,它完全符合OP的要求。 – 2009-09-25 14:44:36

1

这可有助于

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

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

+0

他在问顺序正整数。不是随机的。 – 2009-09-25 10:52:47

4

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

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

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

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; 

这样,你有一个直观的选择您的序列...

希望它有帮助。

+0

疯了! ...它工作。我需要在视图中工作的东西 - 将分配赋值给一个变量会阻止视图。尼斯。 – 2017-07-25 01:55:27

9

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

对于第10个整数(使用mysql.help_relation,但任何表会做),你可以使用下面的查询:

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

这也被放置在服用最小和最大的功能。

+1

感谢您的提示。成功使用以下内容来获取日期范围:'SELECT @i:= DATE_SUB(@i,INTERVAL 1 DAY)date FROM mysql.help_relation,(SELECT @i:= CURRENT_DATE)v WHERE @i> DATE_SUB(CURRENT_DATE,INTERVAL 3个月);'。 – 2014-05-27 13:20:18

+0

这不是一个通用的解决方案。它的工作原理是,只要你使用的表格至少有你想获得的行数。创建一个没有行的虚拟表,并且SELECT @N:= @ N + 1 AS整数FROM dummy(SELECT @N:= 0)dum LIMIT 10不产生行。 – user1645975 2014-09-02 09:36:53

+0

可能会老了,但这太棒了。我知道这样的事情必须存在。 – slicedtoad 2015-02-26 19:53:02

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

0

如果你的数据库支持分析窗口以下功能是简单的作品真的很好:

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

此语句返回一组数字从1到2700