【问题标题】:SQL to generate a list of numbers from 1 to 100SQL 生成从 1 到 100 的数字列表
【发布时间】:2011-02-20 07:01:00
【问题描述】:

使用 DUAL 表,我如何获得从 1 到 100 的数字列表?

【问题讨论】:

  • 这是作业吗?如果不是,“使用 DUAL 表”的包含要求对我来说似乎是任意的和奇怪的。
  • @bart - 使用 DUAL 作为源是生成行问题的众所周知的解决方案,因此将其包含在问题中既不武断也不奇怪。
  • “知道为什么要这样做会很有趣” - 测试单位转换逻辑,或适用于所有小时 (0-23) 或一刻钟 (0-95) 的日期逻辑或类似的详尽测试。

标签: sql oracle plsql


【解决方案1】:

您的问题很难理解,但是如果您想选择从1100 的数字,那么这应该可以解决问题:

Select Rownum r
From dual
Connect By Rownum <= 100

【讨论】:

    【解决方案2】:

    彼得的回答也是我最喜欢的。

    如果您正在寻找更多详细信息,这里有一个很好的概述,IMO,here
    特别有趣的是阅读benchmarks

    【讨论】:

      【解决方案3】:

      ORACLE PL/SQL 中另一个有趣的解决方案:

          SELECT LEVEL n
            FROM DUAL
      CONNECT BY LEVEL <= 100;
      

      【讨论】:

      • 这是普通的 Oracle SQL。它在 PL/SQL 上下文之外也能正常工作。
      【解决方案4】:

      努力去做。使用很棒的MODEL 子句:

      SELECT V
      FROM DUAL
      MODEL DIMENSION BY (0 R)
            MEASURES (0 V)
            RULES ITERATE (100) (
              V[ITERATION_NUMBER] = ITERATION_NUMBER + 1
            )
      ORDER BY 1
      

      证明:http://sqlfiddle.com/#!4/d41d8/20837

      【讨论】:

      • 这很简单,为什么不进行模式匹配... :-)
      • @igr:我挑战你实际提供这个答案:-)
      • CV(R) 是什么意思?它像当前值吗?还是……?
      • @zygimantus,是的,R“当前值” 的语法有些“奇怪”,意思是等式左侧的值。详情请please refer to the Oracle MODEL white paper
      • @lad2025:您当然是对的,非常感谢您的提示!
      【解决方案5】:

      Peter 示例的变体,演示了一种可用于生成 0 到 99 之间的所有数字的方法。

      with digits as (
        select mod(rownum,10) as num 
        from   dual 
        connect by rownum <= 10
      )
      select a.num*10+b.num as num 
      from   digits a
             ,digits b
      order by num
      ;
      

      当您进行批次标识符分配并查找尚未分配的项目时,这样的事情会变得很有用。

      例如,如果您要销售宾果游戏门票,您可能希望分批分配 100 名员工(猜猜我过去是如何为运动筹集资金的)。当他们销售一批时,他们会按顺序获得下一批。但是,购买门票的人可以选择购买该批次中的任何门票。可能会问“售出什么票”这样的问题。

      在这种情况下,我们只有在给定批次中返回的票证的部分随机列表,并且需要所有可能性的完整列表来确定我们没有哪些可能性。

      with range as (
        select mod(rownum,100) as num 
        from   dual 
        connect by rownum <= 100
      ),
      AllPossible as (
        select a.num*100+b.num as TicketNum
        from   batches a
               ,range b
        order by num
      )
      select TicketNum as TicketsSold
      from   AllPossible
      where  AllPossible.Ticket not in (select TicketNum from TicketsReturned)
      ;
      

      请原谅使用了关键词,我从一个真实的例子中更改了一些变量名。

      ...为了证明为什么这样的东西会有用

      【讨论】:

        【解决方案6】:
        SELECT * FROM `DUAL` WHERE id>0 AND id<101
        

        上面的查询是用SQL写在数据库里的。

        【讨论】:

        • 这是针对哪个数据库的?
        【解决方案7】:

        如果您希望将整数绑定在两个整数之间(即以 1 以外的值开头),您可以使用以下内容:

        with bnd as (select 4 lo, 9 hi from dual)
        select (select lo from bnd) - 1 + level r
        from dual
        connect by level <= (select hi-lo from bnd);
        

        它给出:

        4
        5
        6
        7
        8
        

        【讨论】:

          【解决方案8】:

          我创建了一个返回数字表的 Oracle 函数

          CREATE OR REPLACE FUNCTION [schema].FN_TABLE_NUMBERS(
              NUMINI INTEGER,
              NUMFIN INTEGER,
              EXPONENCIAL INTEGER DEFAULT 0
          ) RETURN TBL_NUMBERS
          IS
              NUMEROS TBL_NUMBERS;
              INDICE NUMBER;
          BEGIN
              NUMEROS := TBL_NUMBERS();
          
              FOR I IN (
                  WITH TABLA AS (SELECT NUMINI, NUMFIN FROM DUAL)
                  SELECT NUMINI NUM FROM TABLA UNION ALL
                  SELECT 
                      (SELECT NUMINI FROM TABLA) + (LEVEL*TO_NUMBER('1E'||TO_CHAR(EXPONENCIAL))) NUM
                  FROM DUAL
                  CONNECT BY 
                      (LEVEL*TO_NUMBER('1E'||TO_CHAR(EXPONENCIAL))) <= (SELECT NUMFIN-NUMINI FROM TABLA)
              ) LOOP
                  NUMEROS.EXTEND;
                  INDICE := NUMEROS.COUNT; 
                  NUMEROS(INDICE):= i.NUM;
              END LOOP;
          
              RETURN NUMEROS;
          
          EXCEPTION
            WHEN NO_DATA_FOUND THEN
                 RETURN NUMEROS;
            WHEN OTHERS THEN
                 RETURN NUMEROS;
          END;
          /
          

          是否需要创建新的数据类型:

          CREATE OR REPLACE TYPE [schema]."TBL_NUMBERS" IS TABLE OF NUMBER;
          /
          

          用法:

          SELECT COLUMN_VALUE NUM FROM TABLE([schema].FN_TABLE_NUMBERS(1,10))--integers difference: 1;2;.......;10
          

          如果您需要使用指数表示法的数字之间的小数:

          SELECT COLUMN_VALUE NUM FROM TABLE([schema].FN_TABLE_NUMBERS(1,10,-1));--with 0.1 difference: 1;1.1;1.2;.......;10
          SELECT COLUMN_VALUE NUM FROM TABLE([schema].FN_TABLE_NUMBERS(1,10,-2));--with 0.01 difference: 1;1.01;1.02;.......;10
          

          【讨论】:

            【解决方案9】:

            使用GROUP BY CUBE

            SELECT ROWNUM
            FROM (SELECT 1 AS c FROM dual GROUP BY CUBE(1,1,1,1,1,1,1) ) sub
            WHERE ROWNUM <=100;
            

            Rextester Demo

            【讨论】:

              【解决方案10】:

              你可以使用XMLTABLE:

              SELECT rownum
              FROM XMLTABLE('1 to 100');
              
              -- alternatively(useful for generating range i.e. 10-20)
              SELECT (COLUMN_VALUE).GETNUMBERVAL() AS NUM
              FROM XMLTABLE('1 to 100');
              

              DBFiddle Demo

              【讨论】:

                【解决方案11】:

                使用Oracle的子查询工厂子句:“WITH”,可以选择1到100之间的数字:

                WITH t(n) AS (
                  SELECT 1 from dual
                  UNION ALL
                    SELECT n+1 FROM t WHERE n < 100
                )
                SELECT * FROM t;
                

                【讨论】:

                • 郑重声明,它不是 Oracle 特定的子句,它是标准 CTE 语法,在 SQL ServerOracle中的工作方式相同> :-)
                • Postgres 支持类似的递归 CTE
                猜你喜欢
                • 1970-01-01
                • 2016-12-14
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-04-08
                • 2011-01-23
                相关资源
                最近更新 更多