ORACLE SQL: получить все целые числа между двумя числами - PullRequest
20 голосов
/ 21 сентября 2009

Есть ли способ выбрать числа (целые числа), которые включены между двумя числами с SQL в Oracle; Я не хочу создавать PL / SQL процедуру или функцию.

Например, мне нужно получить числа от 3 до 10. Результатом будут значения 3,4,5,6,7,8,9,10.

Thx.

Ответы [ 12 ]

51 голосов
/ 21 сентября 2009

Этот прием с таблицей DUAL Oracle также работает:

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
5 голосов
/ 21 сентября 2009

Первое, что я делаю , когда я создаю новую базу данных, это создание и заполнение некоторых базовых таблиц.

Один - это список всех целых чисел от -N до N, другой - список дат от 5 лет в прошлом до 10 лет в будущем (запланированное задание может продолжать создавать их по мере необходимости, в будущем) и последнее это список всех часов в течение дня. Например, 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;

Это для DB2 / z с автоматическим запуском транзакции, поэтому кажется, что он имеет голые коммиты.

Да, он занимает (минимальное) пространство, но облегчает написание запросов намного , просто выбирая значения из этих таблиц. Он также очень переносим во всех любых СУБД на основе SQL.

Ваш конкретный запрос будет простым:

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

Значения часов и диапазоны дат весьма полезны для приложений, в которых мы работаем. Это позволяет нам создавать нулевые записи для тех часов дня (или дат), у которых нет реальных данных, чтобы вместо (где нет данных на второе число месяца):

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

вместо этого мы можем получить:

Date       | Quantity
-----------+---------
2009-01-01 |        7
2009-01-02 |        0
2009-01-03 |       27
2009-01-04 |        6
4 голосов
/ 22 сентября 2009

Для этого вы можете использовать предложение MODEL.

SELECT c1 from dual
  MODEL DIMENSION BY (1 as rn)  MEASURES (1 as c1)
  RULES ITERATE (7)
  (c1[ITERATION_NUMBER]=ITERATION_NUMBER+7)
4 голосов
/ 21 сентября 2009
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.

Используется тот же трюк, что и у Тони. Обратите внимание, что когда вы используете SQL * Plus 9, вы должны сделать этот запрос встроенным, как показал вам Тони. В SQL * Plus 10 или выше, выше достаточно.

С уважением, Роб.

2 голосов
/ 26 ноября 2013

этот однострочный запрос поможет вам,

select level lvl from dual where level<:upperbound and 

                              level >:lowerbound connect by level<:limt

Для вашего случая:

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

дайте мне знать, если есть какие-либо разъяснения.

1 голос
/ 20 февраля 2018

Одним из способов получения чисел из диапазона является использование XMLTABLE('start to end'):

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

Демоверсия DBFiddle

1 голос
/ 02 февраля 2015

Это позднее дополнение. Но решение кажется более элегантным и простым в использовании.

Используется конвейерная функция, которую необходимо установить один раз:

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;
/

Тогда вы можете использовать это так:

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

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

Решение зависит от Oracle.

1 голос
/ 30 сентября 2010

Гари, чтобы показать результат, который он объяснил, модельный запрос будет:

ВЫБРАТЬ С1 ОТ ДВОЙНОГО РАЗМЕР МОДЕЛИ ПО (1 как рН)
МЕРЫ (1 как c1) ПРАВИЛА ITERATE (8) (С1 [ITERATION_NUMBER] = ITERATION_NUMBER + 3) ЗАКАЗАТЬ по рН

;)

Я всегда использую:

ВЫБРАТЬ (УРОВЕНЬ - 1) + 3 в результате ОТ двойного ПОДКЛЮЧИТЕ ПО УРОВНЮ <= 8 </p>

Где 3 - начальный номер, а 8 - количество «итераций».

1 голос
/ 21 сентября 2009

Или вы можете использовать Между

Select Column1 from dummy_table where Column2 Between 3 and 10
0 голосов
/ 10 июля 2018
create table numbers (value number);

declare
    x number;
begin
    for x in 7 .. 25
    loop
        insert into numbers values (x);
    end loop;
end;
/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...