SQL-запрос для возврата строк N из двойного

Я хочу записать SQL-запрос, который принимает связывать переменную (скажите: ЦИФРА), и ее вывод состоит из одного столбца и: ЦИФРОВОЕ количество строк, каждой строки, имеющей ее номер строки. т.е. если мы передаем: ЦИФРА как 7, вывод должен быть:

VAL
====
1
2
3
4
5
6
7

Не должно быть никаких фактических Таблиц базы данных в запросе, и никакой МН / код SQL не должен использоваться. т.е. только двойной должен использоваться в запросе

Там какой-либо путь состоит в том, чтобы достигнуть этого?

14
задан OMG Ponies 27 February 2010 в 02:48
поделиться

6 ответов

можно было бы использовать:

 WHERE ROWNUM <= :NUM

... но таблица должна содержать строку, равную или большую до предела в переменной bind. Эта ссылка демонстрирует различные методы генерации номеров строк в Oracle.

Используя CONNECT BY, Oracle 10g+:

SELECT LEVEL
  FROM DUAL
CONNECT BY LEVEL <= :NUM

подтверждает monojohnny, что переменная привязки может быть использована. Попытки запускать Oracle 9i, хотя синтаксис CONNECT BY поддерживается, приводят к ошибке ORA-01436.

Единственное, на чем я не уверен на 100%, это если CONNECT BY примет лимит от переменной bind.

Ссылка:

34
ответ дан 1 December 2019 в 06:48
поделиться

Попробуй что-нибудь вроде:

SELECT 1 AS Val FROM dual
UNION ALL SELECT 2 FROM dual
UNION ALL SELECT 3 FROM dual
UNION ALL SELECT 4 FROM dual
UNION ALL SELECT 5 FROM dual
UNION ALL SELECT 6 FROM dual
UNION ALL SELECT 7 FROM dual;

Это грязно, но это сработает.

Редактировано: Ах - вам нужно передать переменную, чтобы знать, как высоко...

Так что как насчет чего-то вроде:

SELECT t1.Val + t2.Val * 2 + t3.Val * 4 + t4.Val * 8 AS Val
FROM
(
SELECT 0 AS Val FROM dual
UNION ALL SELECT 1 FROM dual
) AS t1, 
(
SELECT 0 AS Val FROM dual
UNION ALL SELECT 1 FROM dual
) AS t2, 
(
SELECT 0 AS Val FROM dual
UNION ALL SELECT 1 FROM dual
) AS t3, 
(
SELECT 0 AS Val FROM dual
UNION ALL SELECT 1 FROM dual
) AS t4
WHERE t1.Val + t2.Val * 2 + t3.Val * 4 + t4.Val * 8 <= 7;

Хорошо... отредактируйте еще раз, теперь используя WITH:

WiTH 
A0 AS (SELECT 0 as N FROM DUAL UNION ALL SELECT 0 FROM DUAL),
A1 AS (SELECT 0 as N FROM A0, A0 AS B),
A2 AS (SELECT 0 as N FROM A1, A1 AS B),
A3 AS (SELECT 0 as N FROM A2, A2 AS B),
A4 AS (SELECT 0 as N FROM A3, A3 AS B),
A5 AS (SELECT 0 as N FROM A4, A4 AS B),
A6 AS (SELECT 0 as N FROM A5, A5 AS B),
Nums AS (SELECT ROW_NUMBER() OVER (ORDER BY N) AS Val FROM A6)
SELECT *
FROM Nums
WHERE Val <= :NUM
;
4
ответ дан 1 December 2019 в 06:48
поделиться

Я не придумал этот ответ [ так что убедитесь, что все голоса идут в правильном направлении!!!] ] , это просто мои тестовые заметки, основанные на 'OMG Ponies' [который не был уверен, будет ли метод работать с переменной связывания] выше для справки:

Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL> var num_rows number
SQL> begin select 20 into :num_rows from dual;
  2  end;
  3  /

PL/SQL procedure successfully completed.

SQL> select level from dual
  2  connect by level <=:num_rows;

     LEVEL
----------
         1
         2
         3
         4
 ...
3
ответ дан 1 December 2019 в 06:48
поделиться

Я помечаю эту вики-сообщество, так как на самом деле она не отвечает вашим требованиям по отсутствию таблиц, но одно из первых, что мы делаем при установке базы данных - это создаём набор таблиц для такого рода целей.

  • Таблица, содержащая большое количество целых чисел (например, -
  • Таблица, содержащая каждую дату от 10 лет в прошлом до 10 лет в будущем (которая постоянно добавляется к каждому месяцу и время от времени обрезается)
  • Таблица, содержащая каждый час дня.

Тем самым мы значительно уменьшаем сложность и увеличиваем скорость большого количества наших запросов за счет (минимального и дешевого) дискового пространства.

Вы должны серьезно подумать об этом. Помимо ведения таблицы дат, в обслуживании не так уж и много нужно.

.
0
ответ дан 1 December 2019 в 06:48
поделиться

В зависимости от базы данных можно использовать различные методы.

PostgreSQL имеет хорошую возможность -- series.

Получить то, что вы хотите, можно просто:

SELECT * FROM generate_series(1, NUM);
-1
ответ дан 1 December 2019 в 06:48
поделиться

Другое решение потребует некоторого PL/SQL для создания функции возврата коллекции со строками... Не так просто, как подход уровня select из двойного соединения по уровню <= :b1, но это полезно в нескольких ситуациях:

1) Создать тип объекта number table ( number_tbl, в данном примере ) :

create or replace type number_tbl as table of number;

2) Создать функцию, которая будет получать количество генерируемых строк, а затем вернуть объект number_tbl с результатами:

create or replace function get_rows( i_num_rows number ) return number_tbl as
  t number_tbl := number_tbl();
begin
  if i_num_rows < 1 then
    return null;
  end if;

  t.extend( i_num_rows );

  for i in 1..i_num_rows loop
    t(i) := i;
  end loop;

  return t;
end get_rows;

3) select из вашей функции с помощью функции table( . ... ) для превращения вашего объекта number_tbl в нечто выбираемое:

select * from table( cast ( get_rows( :b1 ) as number_tbl ) );
0
ответ дан 1 December 2019 в 06:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: