sql >> Base de Datos >  >> RDS >> Oracle

UNPIVOT en un número indeterminado de columnas

Parece que desea deshacer la rotación de la tabla (girar implicaría pasar de muchas filas y 2 columnas a 1 fila con muchas columnas). Lo más probable es que necesite usar SQL dinámico para generar la consulta y luego usar DBMS_SQL paquete (o potencialmente EXECUTE IMMEDIATE ) para ejecutarlo. También debería poder construir una función de tabla segmentada que hiciera el despívot. También necesitaría usar SQL dinámico dentro de la función de tabla canalizada, pero potencialmente sería menos código. Esperaría una declaración SQL dinámica pura usando UNPIVOT aunque para ser más eficiente.

Un enfoque ineficiente, pero relativamente fácil de seguir, sería algo como

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.

Luego puede llamar eso en una declaración SQL (creo que querría al menos una tercera columna con el nombre de la columna)

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 enfoque más eficiente sería adaptar la función de tabla segmentada show_table de Tom Kyte.