Pivote dinámico en SQL de Oracle

Resuelto prabhakar asked hace 11 años • 10 respuestas

... pivote (suma(A) para B en (X))

Ahora B es del tipo de datos varchar2 y X es una cadena de valores varchar2 separados por comas.
Los valores para X son valores distintos seleccionados de una columna (digamos CL) de la misma tabla. De esta manera estaba funcionando la consulta dinámica.

Pero el problema es que cada vez que hay un nuevo valor en la columna CL tengo que agregarlo manualmente a la cadena X.

Intenté reemplazar X con valores distintos seleccionados de CL. Pero la consulta no se está ejecutando.
La razón por la que sentí se debió al hecho de que para reemplazar X necesitamos valores separados por comas.
Luego creé una función para devolver un resultado exacto que coincida con la cadena X. Pero la consulta aún no se ejecuta.
Los mensajes de error que se muestran son como "faltan paréntesis correctas", "fin del canal de comunicación del archivo", etc.
Intenté pivotar xml en lugar de simplemente pivotar, la consulta se ejecuta pero proporciona valores como oraxxx, etc., que no son valores en absoluto.

Quizás no lo estoy usando correctamente.
¿Puedes decirme algún método para crear un pivote con valores dinámicos?

prabhakar avatar Mar 19 '13 11:03 prabhakar
Aceptado

No se puede colocar una declaración dinámica en la declaración IN de PIVOT sin usar PIVOT XML, que genera resultados menos deseables. Sin embargo, puede crear una cadena IN e ingresarla en su declaración.

Primero, aquí está mi tabla de muestra;

  myNumber    myValue myLetter
---------- ---------- --------
         1          2 A        
         1          4 B        
         2          6 C        
         2          8 A        
         2         10 B        
         3         12 C        
         3         14 A      

Primero configure la cadena para usar en su declaración IN. Aquí estás poniendo la cadena en "str_in_statement". Estamos usando COLUMNA NEW_VALUE y LISTAGG para configurar la cadena.

clear columns
COLUMN temp_in_statement new_value str_in_statement
SELECT DISTINCT 
    LISTAGG('''' || myLetter || ''' AS ' || myLetter,',')
        WITHIN GROUP (ORDER BY myLetter) AS temp_in_statement 
    FROM (SELECT DISTINCT myLetter FROM myTable);

Tu cadena se verá así:

'A' AS A,'B' AS B,'C' AS C

Ahora use la declaración String en su consulta PIVOT.

SELECT * FROM 
    (SELECT myNumber, myLetter, myValue FROM myTable)
    PIVOT (Sum(myValue) AS val FOR myLetter IN (&str_in_statement));

Aquí está el resultado:

  MYNUMBER      A_VAL      B_VAL      C_VAL
---------- ---------- ---------- ----------
         1          2          4            
         2          8         10          6 
         3         14                    12 

Sin embargo, existen limitaciones. Sólo puedes concatenar una cadena de hasta 4000 bytes.

user2179919 avatar May 16 '2014 15:05 user2179919

No se puede poner una cadena no constante en la INcláusula de la cláusula dinámica.
Puedes usar Pivot XML para eso.

De la documentación :

subconsulta Una subconsulta se utiliza sólo junto con la palabra clave XML. Cuando especifica una subconsulta, todos los valores encontrados por la subconsulta se utilizan para pivotar

Debe tener un aspecto como este:

select xmlserialize(content t.B_XML) from t_aa
pivot xml(
sum(A) for B in(any)
) t;

También puedes tener una subconsulta en lugar de la ANYpalabra clave:

select xmlserialize(content t.B_XML) from t_aa
pivot xml(
sum(A) for B in (select cl from t_bb)
) t;

Aquí hay una demostración de sqlfiddle.

A.B.Cade avatar Mar 19 '2013 05:03 A.B.Cade

Para lectores posteriores, aquí hay otra solución https://technology.amis.nl/2006/05/24/dynamic-sql-pivoting-stealing-antons-thunder/

permitiendo una consulta como

select * from table( pivot(  'select deptno,  job, count(*) c from scott.emp group by deptno,job' ) )
Scott avatar Jul 15 '2015 02:07 Scott