3

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

人
-----------------
person_id 姓名
-----------------
P1 ABC
P2 XYZ
联系人
--------------------------------
person_id phone_type phone_no
--------------------------------
P1 电话1 12345
P1 电话2 23455
P2电话1 67897
P2电话3 89786

我需要创建一个看起来像的视图 v_pc

v_pc
person_id 姓名 phone1 phone2 phone3
-------------------------------------
P1 美国广播公司 12345 23455  
P2 Xyz 67897 89786

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

有什么办法可以让联系人表旋转,但使用动态旋转子句,比如

选择 *
 从 (
    选择
        person_idd,
        电话类型,
        电话号码
    来自联系人
 ) PIVOT (MAX(phone_no) FOR phone_type IN ('phone1','phone2','phone3'))

我还尝试在带有数据透视的情况下使用 XML 子句,因此使用动态数据透视子句,即提取 XML 中的结果,然后使用 XMLTABLE 重新创建列。但我无法达到预期的结果。

4

2 回答 2

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,所以我猜您还是在使用它。

于 2012-08-22T10:00:16.373 回答
0

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

于 2013-02-06T07:39:18.933 回答