简体   繁体   English

ORACLE SQL:获取两个数字之间的所有整数

[英]ORACLE SQL:Get all integers between two numbers

Is there any way to select the numbers (integers) that are included between two numbers with SQL in Oracle;有没有什么办法可以在Oracle中用SQL选择两个数字之间包含的数字(整数); I don't want to create PL/SQL procedure or function.我不想创建 PL/SQL 过程或函数。

For example I need to get the numbers between 3 and 10. The result will be the values 3,4,5,6,7,8,9,10.例如,我需要获取 3 到 10 之间的数字。结果将是值 3、4、5、6、7、8、9、10。

Thx.谢谢。

This trick with Oracle's DUAL table also works: Oracle 的 DUAL 表的这个技巧也有效:

SQL> select n from
  2  ( select rownum n from dual connect by level <= 10)
  3  where n >= 3;

         N
----------
         3
         4
         5
         6
         7
         8
         9
        10

The first thing I do when I create a new database is to create and populate some basic tables.创建新数据库时,我做的第一件事是创建并填充一些基本表。

One is a list of all integers between -N and N, another is a list of dates 5 years in the past through 10 years in the future (a scheduled job can continue creating these as needed, going forward) and the last is a list of all hours throughout the day.一个是 -N 和 N 之间所有整数的列表,另一个是过去 5 年到未来 10 年的日期列表(预定的作业可以根据需要继续创建这些,向前推进),最后一个是列表全天所有时间。 For example, the inetgers:例如, inetgers:

create table numbers (n integer primary key);
insert into numbers values (0);
insert into numbers select n+1 from numbers; commit;
insert into numbers select n+2 from numbers; commit;
insert into numbers select n+4 from numbers; commit;
insert into numbers select n+8 from numbers; commit;
insert into numbers select n+16 from numbers; commit;
insert into numbers select n+32 from numbers; commit;
insert into numbers select n+64 from numbers; commit;
insert into numbers select n+128 from numbers; commit;
insert into numbers select n+256 from numbers; commit;
insert into numbers select n+512 from numbers; commit;
insert into numbers select n+1024 from numbers; commit;
insert into numbers select n+2048 from numbers; commit;
insert into numbers select n+4096 from numbers; commit;
insert into numbers select n+8192 from numbers; commit;
insert into numbers select -n from numbers where n > 0; commit;

This is for DB2/z which has automatic transaction start which is why it seems to have naked commits.这适用于具有自动事务启动的 DB2/z,这就是为什么它似乎具有裸提交。

Yes, it takes up a (minimal) space but it makes queries much easier to write, simply by selecting values from those tables.是的,它占用(最小)空间,但它使查询容易编写,只需从这些表中选择值即可。 It's also very portable across pretty much any SQL-based DBMS.它在几乎所有基于 SQL 的 DBMS 中也非常具有可移植性。

Your particular query would then be a simple:您的特定查询将是一个简单的:

select n from numbers where n >=3 and n <= 10;

The hour figures and date ranges are quite useful for the sort of reporting applications we work on.小时数字和日期范围对于我们处理的报告应用程序非常有用。 It allows us to create zero entries for those hours of the day (or dates) which don't have any real data so that, instead of (where there's no data on the second of the month):它允许我们为没有任何真实数据的一天中的那些小时(或日期)创建零条目,而不是(当月的第二个没有数据的地方):

Date       | Quantity
-----------+---------
2009-01-01 |        7
2009-01-03 |       27
2009-01-04 |        6

we can instead get:我们可以改为:

Date       | Quantity
-----------+---------
2009-01-01 |        7
2009-01-02 |        0
2009-01-03 |       27
2009-01-04 |        6
SQL> var N_BEGIN number
SQL> var N_END number
SQL> exec :N_BEGIN := 3; :N_END := 10

PL/SQL procedure successfully completed.

SQL>  select :N_BEGIN + level - 1 n
  2     from dual
  3  connect by level <= :N_END - :N_BEGIN + 1
  4  /

         N
----------
         3
         4
         5
         6
         7
         8
         9
        10

8 rows selected.

This uses the same trick as Tony's.这使用与托尼相同的技巧。 Note that when you are using SQL*Plus 9, you have to make this query an inline view as Tony showed you.请注意,当您使用 SQL*Plus 9 时,您必须使此查询成为内联视图,正如 Tony 向您展示的那样。 In SQL*Plus 10 or higher, the above is sufficient.在 SQL*Plus 10 或更高版本中,上述内容就足够了。

Regards, Rob.问候,罗布。

You can use the MODEL clause for this.您可以为此使用 MODEL 子句。

SELECT c1 from dual
  MODEL DIMENSION BY (1 as rn)  MEASURES (1 as c1)
  RULES ITERATE (7)
  (c1[ITERATION_NUMBER]=ITERATION_NUMBER+7)

this single line query will help you,这个单行查询会帮助你,

select level lvl from dual where level<:upperbound and 

                              level >:lowerbound connect by level<:limt

For your case:对于您的情况:

select level lvl from dual where level<10 and level >3 connect by level<11

let me know if any clarification.如果有任何澄清,请告诉我。

或者你可以使用之间

Select Column1 from dummy_table where Column2 Between 3 and 10

This is a late addition.这是一个迟到的补充。 But the solution seems to be more elegant and easier to use.但该解决方案似乎更优雅,更易于使用。

It uses a pipelined function that has to be installed once:它使用一个必须安装一次的流水线函数:

CREATE TYPE number_row_type AS OBJECT 
(
  num NUMBER
);

CREATE TYPE number_set_type AS TABLE OF number_row_type;

CREATE OR REPLACE FUNCTION number_range(p_start IN PLS_INTEGER, p_end IN PLS_INTEGER)
    RETURN number_set_type
    PIPELINED
IS
    out_rec number_row_type := number_row_type(NULL);

BEGIN
  FOR i IN p_start .. p_end LOOP
    out_rec.num := i;
    pipe row(out_rec);
  END LOOP;

END number_range;
/

Then you can use it like this:然后你可以像这样使用它:

select * from table(number_range(1, 10));

NUM
---
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10

The solution is Oracle specific.解决方案是特定于 Oracle 的。

Gary, to show the result that he explained, the model query will be: Gary,为了显示他解释的结果,模型查询将是:

SELECT c1 FROM DUAL MODEL DIMENSION BY (1 as rn) SELECT c1 from DUAL MODEL DIMENSION BY (1 as rn)
MEASURES (1 as c1) RULES ITERATE (8) (c1[ITERATION_NUMBER]=ITERATION_NUMBER+3) ORDER BY rn测量(1 作为 c1)规则迭代 (8) (c1[ITERATION_NUMBER]=ITERATION_NUMBER+3) ORDER BY rn

;) ;)

I always use:我总是使用:

SELECT (LEVEL - 1) + 3 as result FROM Dual CONNECT BY Level <= 8 SELECT (LEVEL - 1) + 3 as result FROM Dual CONNECT BY Level <= 8

Where 3 is the start number and 8 is the number of "iterations".其中 3 是起始编号,8 是“迭代次数”。

One way to generate numbers from range is to use XMLTABLE('start to end') :从范围生成数字的一种方法是使用XMLTABLE('start to end')

SELECT TO_NUMBER(column_value)  integer_value
FROM XMLTABLE('3 to 10');

I added TO_NUMBER because COLUMN_VALUE is a string我添加了 TO_NUMBER 因为 COLUMN_VALUE 是一个字符串

DBFiddle Demo DBFiddle 演示

I want to share an usefull query that converts a string of comma and '-' separated list of numbers into a the equivalent expanded list of numbers:我想分享一个有用的查询,它将一串逗号和“-”分隔的数字列表转换为等效的扩展数字列表:

An example that converts '1,2,3,50-60' into将 '1,2,3,50-60' 转换为的示例

1
2
3
50
51
...
60
select distinct * from (SELECT (LEVEL - 1) + mini as result FROM (select REGEXP_SUBSTR (value, '[^-]+', 1, 1)mini ,nvl(REGEXP_SUBSTR (value, '[^-]+', 1, 2),0) maxi from (select REGEXP_SUBSTR (value, '[^,]+', 1, level) as value from (select '1,2,3,50-60' value from dual) connect by level <= length(regexp_replace(value,'[^,]*'))+1)) CONNECT BY Level <= (maxi-mini+1)) order by 1 asc;

You may use it as a view and parametrize the '1,2,3,50-60' string您可以将其用作视图并参数化 '1,2,3,50-60' 字符串

create table numbers (value number);

declare
    x number;
begin
    for x in 7 .. 25
    loop
        insert into numbers values (x);
    end loop;
end;
/

In addition to the answers already provided, it is possible to combine the listagg function with connect by to obtain the result in the format mentioned in the question.除了已经提供的答案之外,还可以将 listagg 函数与 connect by 结合使用,以获得问题中提到的格式的结果。 See a code example below:请参阅下面的代码示例:

SELECT 
   DBMS_LOB.SUBSTR(LISTAGG(S.INTEGERS,',' ) WITHIN GROUP (ORDER BY S.INTEGERS), 300,1) RESULT 
FROM 
   (SELECT 
      INTEGERS 
   FROM 
      ( SELECT ROWNUM INTEGERS FROM DUAL CONNECT BY LEVEL <= 10) 
   WHERE 
      INTEGERS >= 3 
   ) S;

OutPut:输出:

SQL> 
RESULT
----------------
3,4,5,6,7,8,9,10

I just did a table valued function to do this in SQL server, if anyone is interested, this works flawlessly.我只是做了一个表值函数来在 SQL 服务器中执行此操作,如果有人感兴趣,它可以完美运行。

CREATE FUNCTION [dbo].[NumbersBetween]
(
    @StartN int,
    @EndN int
)
RETURNS 
@NumberList table
(
    Number int
)

AS

BEGIN

WHILE @StartN <= @EndN
    BEGIN
    insert into @NumberList
    VALUES (@StartN)
    set @StartN = @StartN + 1
    END

Return

END
GO

If you run the query: "select * from dbo.NumbersBetween(1,5)" (w/o the quotes of course) the result will be如果您运行查询:“select * from dbo.NumbersBetween(1,5)”(当然没有引号)结果将是

Number
-------
1
2
3
4
5

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM