Pivote dinámico en SQL de Oracle
... 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?
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.
No se puede poner una cadena no constante en la IN
clá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 ANY
palabra 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.
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' ) )