2010-09-08 1 views
10

Я использую oracle для вывода позиций в приложении для покупок. Каждый элемент имеет поле количества, которое может быть больше 1, и если оно есть, я хотел бы вернуть эту строку N раз.Как я могу возвратить несколько одинаковых строк на основе поля количества в самой строке?

Вот что я имею в виду за столом

product_id, quanity 
1, 3, 
2, 5 

И я ищу запрос, который будет возвращать

1,3 
1,3 
1,3 
2,5 
2,5 
2,5 
2,5 
2,5 

Возможно ли это? Я видел this ответ для SQL Server 2005, и я ищу почти точную вещь в оракуле. Создание специальной таблицы номеров, к сожалению, не является вариантом.

ответ

15

Я использовал 15 как максимум для примера, но вы должны установить его на 9999 или любое максимальное количество, которое вы будете поддерживать.

create table t (product_id number, quantity number); 
insert into t values (1,3); 
insert into t values (2,5); 

select t.* 
    from t 
    join (select rownum rn from dual connect by level < 15) a 
           on a.rn <= t.quantity 
order by 1; 
+1

спасибо, это именно то, что я искал. – user126715

4

Сначала создайте образец данных:

create table my_table (product_id number , quantity number); 
insert into my_table(product_id, quantity) values(1,3); 
insert into my_table(product_id, quantity) values(2,5); 

И теперь запустить этот SQL:

SELECT product_id, quantity 
    FROM my_table tproducts 
     ,( SELECT LEVEL AS lvl 
       FROM dual 
      CONNECT BY LEVEL <= (SELECT MAX(quantity) FROM my_table)) tbl_sub 
    WHERE tbl_sub.lvl BETWEEN 1 AND tproducts.quantity 
ORDER BY product_id, lvl; 

PRODUCT_ID QUANTITY 
---------- ---------- 
     1   3 
     1   3 
     1   3 
     2   5 
     2   5 
     2   5 
     2   5 
     2   5 

Этот вопрос является Propably же, как это: how to calc ranges in oracle

раствора Update, для Oracle 9i:

Вы можете использовать pipelined_function(), как это:

CREATE TYPE SampleType AS OBJECT 
(
    product_id number, 
    quantity varchar2(2000) 
) 
/

CREATE TYPE SampleTypeSet AS TABLE OF SampleType 
/

CREATE OR REPLACE FUNCTION GET_DATA RETURN SampleTypeSet 
PIPELINED 
IS 
    l_one_row SampleType := SampleType(NULL, NULL); 

BEGIN 

    FOR cur_data IN (SELECT product_id, quantity FROM my_table ORDER BY product_id) LOOP 
     FOR i IN 1..cur_data.quantity LOOP 
      l_one_row.product_id := cur_data.product_id; 
      l_one_row.quantity := cur_data.quantity; 
      PIPE ROW(l_one_row); 
     END LOOP; 
    END LOOP; 

    RETURN; 
END GET_DATA; 
/

Теперь вы можете сделать это:

SELECT * FROM TABLE(GET_DATA()); 

Или это:

CREATE OR REPLACE VIEW VIEW_ALL_DATA AS SELECT * FROM TABLE(GET_DATA()); 
SELECT * FROM VIEW_ALL_DATA; 

Оба с теми же результатами.

(на основе моей статьи pipelined function)

+0

Вы используете 11g? Я никогда не мог запустить подзапрос в разделе «connect by level» в 9i. –

+0

Вы правы, на Oracle 9i ошибка повышения: ORA-01473. Я напишу лучшее решение для Oracle 9i ... подождите минуту, я обнов свой «ответ» :) –

+0

теперь ответ обновлен для решения Oracle 9i. –