sql - multiple - Girar filas en columnas dinĂ¡micamente en Oracle
sql oracle convertir columnas en filas (4)
Tengo la siguiente tabla de Oracle 10g llamada _kv:
select * from _kv
ID K V
---- ----- -----
1 name Bob
1 age 30
1 gender male
2 name Susan
2 status married
Me gustaría convertir mis claves en columnas usando SQL simple (no PL / SQL) para que la tabla resultante se vea así:
ID NAME AGE GENDER STATUS
---- ----- ----- ------ --------
1 Bob 30 male
2 Susan married
- La consulta debe tener tantas columnas como
K
s únicos existan en la tabla (no hay tantas) - No hay forma de saber qué columnas pueden existir antes de ejecutar la consulta.
- Estoy tratando de evitar ejecutar una consulta inicial para construir programáticamente la consulta final.
- Las celdas en blanco pueden ser nulas o cadenas vacías, realmente no importa.
- Estoy usando Oracle 10g, pero una solución 11g también estaría bien.
Hay muchos ejemplos para cuando sepa a qué columnas se les puede llamar, pero no puedo encontrar una solución pivote genérica para Oracle.
¡Gracias!
Antes que nada, pivotear dinámicamente usando pivot xml
nuevamente necesita ser analizado. Tenemos otra forma de hacerlo almacenando los nombres de columna en una variable y pasándolos en el sql dinámico como se muestra a continuación.
Considere que tenemos una tabla como la siguiente.
Si necesitamos mostrar los valores en la columna YR
como nombres de columna y los valores en esas columnas de QTY
, entonces podemos usar el siguiente código.
declare
sqlqry clob;
cols clob;
begin
select listagg('''''''' || YR || '''''' as "'' || YR || ''"'', '','') within group (order by YR)
into cols
from (select distinct YR from EMPLOYEE);
sqlqry :=
''
select * from
(
select *
from EMPLOYEE
)
pivot
(
MIN(QTY) for YR in ('' || cols || '')
)'';
execute immediate sqlqry;
end;
/
RESULTADO
Oracle 11g proporciona una operación PIVOT
que hace lo que desea.
Solución Oracle 11g
select * from
(select id, k, v from _kv)
pivot(max(v) for k in (''name'', ''age'', ''gender'', ''status'')
(Nota: no tengo una copia de 11g para probar esto, así que no he verificado su funcionalidad)
Obtuve esta solución de: http://orafaq.com/wiki/PIVOT
EDITAR - opción pivot xml (también Oracle 11g)
Aparentemente también hay una opción pivot xml
para cuando no conoce todos los posibles encabezados de columna que pueda necesitar. (vea la sección de XML TYPE cerca de la parte inferior de la página ubicada en http://www.oracle.com/technetwork/articles/sql/11g-pivot-097235.html )
select * from
(select id, k, v from _kv)
pivot xml (max(v)
for k in (any) )
(Nota: como antes, no tengo una copia de 11g para probar esto, así que no he verificado su funcionalidad)
Edit2: Cambió v
en las v
pivot
y pivot xml
a max(v)
ya que se supone que debe agregarse como se menciona en uno de los comentarios. También agregué la cláusula in
que no es opcional para pivot
. Por supuesto, tener que especificar los valores en la cláusula in
frustra el objetivo de tener una consulta pivote / tabla de referencias completamente dinámica como era el deseo del cartel de esta pregunta.
Para manejar situaciones donde hay una posibilidad de valores múltiples (v en su ejemplo), uso PIVOT
y LISTAGG
:
SELECT * FROM
(
SELECT id, k, v
FROM _kv
)
PIVOT
(
LISTAGG(v ,'','')
WITHIN GROUP (ORDER BY k)
FOR k IN (''name'', ''age'',''gender'',''status'')
)
ORDER BY id;
Como desea valores dinámicos, utilice SQL dinámico y pase los valores determinados ejecutando una selección en los datos de la tabla antes de llamar a la instrucción dinámica.
Pase para tener una tarea en pivote. Debajo funciona para mí según lo probado ahora en 11g:
select * from
(
select ID, COUNTRY_NAME, TOTAL_COUNT from ONE_TABLE
)
pivot(
SUM(TOTAL_COUNT) for COUNTRY_NAME in (
''Canada'', ''USA'', ''Mexico''
)
);