Oracle
 sql >> Database >  >> RDS >> Oracle

UNPIVOT su un numero indeterminato di colonne

Sembra che tu voglia annullare il pivot della tabella (il pivot comporterebbe il passaggio da molte righe e 2 colonne a 1 riga con molte colonne). Molto probabilmente dovrai utilizzare l'SQL dinamico per generare la query e quindi utilizzare il DBMS_SQL pacchetto (o potenzialmente EXECUTE IMMEDIATE ) per eseguirlo. Dovresti anche essere in grado di costruire una funzione di tabella pipeline che ha eseguito l'annullamento del pivot. Dovresti usare anche l'SQL dinamico all'interno della funzione della tabella pipeline, ma potenzialmente sarebbe meno codice. Mi aspetterei un'istruzione SQL dinamica pura usando UNPIVOT per essere più efficienti, però.

Un approccio inefficiente, ma relativamente facile da seguire, sarebbe qualcosa del tipo

SQL> ed
Wrote file afiedt.buf

  1  create or replace type emp_unpivot_type
  2  as object (
  3    empno number,
  4    col   varchar2(4000)
  5* );
SQL> /

Type created.

SQL> create or replace type emp_unpivot_tbl
  2  as table of emp_unpivot_type;
  3  /

Type created.

SQL> ed
Wrote file afiedt.buf

  1  create or replace function unpivot_emp
  2  ( p_empno in number )
  3    return emp_unpivot_tbl
  4    pipelined
  5  is
  6    l_val varchar2(4000);
  7  begin
  8    for cols in (select column_name from user_tab_columns where table_name = 'EMP')
  9    loop
 10      execute immediate 'select ' || cols.column_name || ' from emp where empno = :empno'
 11         into l_val
 12       using p_empno;
 13      pipe row( emp_unpivot_type( p_empno, l_val ));
 14    end loop;
 15    return;
 16* end;
SQL> /

Function created.

Puoi quindi chiamarlo in un'istruzione SQL (penso che tu voglia almeno una terza colonna con il nome della colonna)

SQL> ed
Wrote file afiedt.buf

  1  select *
  2*   from table( unpivot_emp( 7934 ))
SQL> /

     EMPNO COL
---------- ----------------------------------------
      7934 7934
      7934 MILLER
      7934 CLERK
      7934 7782
      7934 23-JAN-82
      7934 1301
      7934
      7934 10

8 rows selected.

Un approccio più efficiente sarebbe quello di adattare la funzione di tabella pipeline show_table di Tom Kyte.