带有可变列的SQL Pivot

时间:2012-08-22 09:22:28

标签: sql oracle pivot

我有两个表说(person_id,名称)和另一个表联系人(person_id,phone_type,phone_no)。

Person
-----------------
person_id    name
-----------------
P1           Abc 
P2           Xyz
Contacts
--------------------------------
person_id   phone_type  phone_no
--------------------------------
P1          phone1      12345
P1          phone2      23455
P2          phone1      67897
P2          phone3      89786

我需要创建一个类似于

的视图v_pc
v_pc
person_id  name phone1 phone2 phone3
-------------------------------------
P1         Abc  12345  23455  
P2         Xyz  67897         89786

,即,行的联系人表格被旋转以形成视图的列(列数将根据'phone_types'列的不同值变化)。

有什么方法可以透视联系人表,但使用动态pivot-in-clause,类似于

SELECT *
 FROM (
    SELECT
        person_idd,
        phone_type,
        phone_no
    FROM contacts
 ) PIVOT (MAX(phone_no) FOR phone_type IN ('phone1','phone2','phone3'))

我还尝试在with pivot中使用XML子句,因此使用动态pivot-in-clause,即在XML中提取结果,然后使用XMLTABLE重新创建列。但我无法达到预期的结果。

2 个答案:

答案 0 :(得分:2)

您可以使用动态SQL(假设您有一个SYS_REFCURSOR类型的绑定变量v_cur):

declare
  v_sql varchar2(32000);
  v_phonetypes varchar2(32000);
begin
  -- base SQL statement
  v_sql := 'SELECT *
    FROM (
      SELECT
        person_id,
        phone_type,
        phone_no
      FROM contacts
    ) PIVOT (MAX(phone_no) FOR phone_type IN (';

  -- comma-separated list of phone types
  select 
    listagg('''' || phone_type || '''', ',') within group (order by phone_type) 
  into v_phonetypes 
  from (select distinct phone_type from contacts);

  v_sql := v_sql || v_phonetypes || '))';
  dbms_output.put_line(v_sql);
  -- execute query 
  open :v_cur for v_sql;
end;

LISTAGG()需要11gR2,但由于你正在使用PIVOT,我猜你还是在使用它。

答案 1 :(得分:0)

为什么不尝试使用动态SQL创建视图?只需按照Frank在上面创建PIVOT查询的方式设计CREATE语句。然后执行两个,首先是CREATE语句,稍后再执行PIVOT查询。