Oracle数据库 - 动态列数

时间:2013-09-06 06:05:36

标签: sql oracle dynamic

我有以下3个Oracle数据库表:

application (app_id, application_name)      

例如。 (1,firstapp)

item_request (app_id, item_id, qty_requested)   

例如。 (1,111,5),(1,112,3),(1,113,7)

item (item_id, item_code)

例如。 (111,“COMPUTER”),(112,“PHONE”),(113,“DESK”)

我想制作这张表:

new table (app_id, 
           application_name, 
           qty_requested_for_item_with_item_code_111,
           qty_requested_for_item_with_item_code_112,
           qty_requested_for_item_with_item_code_113, 
           etc...)

例如。 (1,fistapp,5,3,7等......)

这甚至可能吗?

3 个答案:

答案 0 :(得分:1)

Oracle对Pivot功能的支持有限。

参见例如http://www.oracle.com/technetwork/articles/sql/11g-pivot-097235.html

简而言之,对于常规输出,您可能会遇到要转入的静态列列表。

对于动态数据透视表,您可以使用pivot xml函数。但是这会在xml中生成pivot列,因此需要解析。

答案 1 :(得分:1)

您可以使用动态SQL实现此目的,例如:使用引用游标。你必须

a)迭代所有现有项目

b)通过添加所有项目来构建您的SELECT列表

c)执行旋转(使用PIVOT或使用传统的MAX / CASE / GROUP BY)方法

create table application(app_id number primary key, application_name varchar2(30));
create table item_request(app_id number, item_id number, qty_requested number);
create table item(item_id number primary key, item_code varchar2(30));

insert into application values(1, 'firstapp');
insert into application values(2, 'secondapp');
insert into item values (111, 'Computer');
insert into item values (112, 'Phone');
insert into item values (113, 'Desk');
insert into item_request values (1, 111, 5);
insert into item_request values (1, 112, 3);
insert into item_request values (1, 113, 7);
insert into item_request values (2, 111, 3);

-- SQL/Plus syntax for declaring and using a bind variable of type ref cursor
var x refcursor;

set autoprint on

declare
  l_sql varchar2(4000);
  l_select varchar2(4000);
  l_from varchar2(4000);
begin
  l_select := 'select application.app_id, application.application_name';
  for cur in (select * from item)
    loop
        l_select := l_select || chr(10) || ',max(case when item_code = ''' || cur.item_code || ''' then qty_requested else 0 end) as ' || cur.item_code;
      end loop;
  l_sql := l_select || ' 
    from application 
    left join item_request on application.app_id = item_request.app_id 
    left join item on item.item_id = item_request.item_id
    group by application.app_id, application.application_name';
  dbms_output.put_line(l_sql);
  open :x for l_sql;
end;      

答案 2 :(得分:0)

您可以根据app_id申请和项目请求,并根据itemid执行数据透视并获取数量。

select * from (select app_id, item_id, qty from application a, item_request ir 
where a.app_id = ir.app_id) pivot(sum(qty) for item_id in (Item List)).

如果item_id列表已完成,则item_id列表使用选择查询代替项目列表。