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

Pivote dinámico de Oracle

El uso de sql dinámico para obtener un resultado en el que las columnas son desconocidas en el momento de la ejecución es un poco complicado en Oracle en comparación con otros RDMBS.

Debido a que aún se desconoce el tipo de registro para la salida, no se puede definir de antemano.

En Oracle 11g, una forma es usar un procedimiento sin nombre que genera una tabla temporal con el resultado pivotado.

Luego seleccione los resultados de esa tabla temporal.

declare
  v_sqlqry clob;
  v_cols clob;
begin
  -- Generating a string with a list of the unique names
  select listagg(''''||CCL||''' as "'||CCL||'"', ', ') within group (order by CCL)
  into v_cols
  from 
  (
    select distinct CCL
    from tableA
  );

  -- drop the temporary table if it exists
  EXECUTE IMMEDIATE 'DROP TABLE tmpPivotTableA';
  EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF;

  -- A dynamic SQL to create a temporary table 
  -- based on the results of the pivot
  v_sqlqry := '
    CREATE GLOBAL TEMPORARY TABLE tmpPivotTableA
    ON COMMIT PRESERVE ROWS AS
    SELECT * 
    FROM (SELECT ID, CCL, Flag FROM TableA) src 
    PIVOT (MAX(Flag) FOR (CCL) IN ('||v_cols||')) pvt';

  -- dbms_output.Put_line(v_sqlqry); -- just to check how the sql looks like
  execute immediate v_sqlqry;

end;
/

select * from tmpPivotTableA;

Devoluciones:

ID  adam john rob terry
--  ---- ---- --- -----
1   x    x    x
2        x      

Puede encontrar una prueba en db<>fiddle aquí

En Oracle 11g, se puede encontrar otro truco interesante (creado por Anton Scheffer) en este blog. Pero tendrá que agregar la función pivote para ello.
El código fuente se puede encontrar en este zip

Después de eso, el SQL puede ser tan simple como esto:

select * from 
table(pivot('SELECT ID, CCL, Flag FROM TableA'));

Encontrará una prueba en db<>fiddle aquí