Saltar al contenido

Pivotar filas en varias columnas

Contamos con la contestación a esta obstáculo, o por lo menos eso deseamos. Si tienes alguna duda dínoslo, que sin dudarlo te responderemos

Solución:

Hay algunas formas de realizar esta transformación de datos. Tienes acceso a la PIVOT entonces esa será la más fácil, pero si no, entonces puede usar una función agregada y una CASE.

Versión agregada/caso:

select personid,
  max(case when optionid = 'A' then 1 else 0 end) OptionA,
  max(case when optionid = 'B' then 1 else 0 end) OptionB,
  max(case when optionid = 'C' then 1 else 0 end) OptionC
from PersonOptions
group by personid
order by personid;

Ver SQL Fiddle con demostración

Pivote estático:

select *
from
(
  select personid, optionid
  from PersonOptions
) src
pivot
(
  count(optionid)
  for optionid in ('A' as OptionA, 'B' OptionB, 'C' OptionC)
) piv
order by personid

Ver SQL Fiddle con demostración

Versión dinámica:

Las dos versiones anteriores funcionan muy bien si tiene una cantidad conocida de valores, pero si sus valores son desconocidos, querrá implementar sql dinámico y en Oracle puede usar un procedimiento:

CREATE OR REPLACE procedure dynamic_pivot_po(p_cursor in out sys_refcursor)
as
    sql_query varchar2(1000) := 'select personid ';

    begin
        for x in (select distinct OptionID from PersonOptions order by 1)
        loop
            sql_query := sql_query ||
                ' , min(case when OptionID = '''||x.OptionID||''' then 1 else null end) as Option_'||x.OptionID;

                dbms_output.put_line(sql_query);
        end loop;

        sql_query := sql_query || ' from PersonOptions group by personid order by personid';
        dbms_output.put_line(sql_query);

        open p_cursor for sql_query;
    end;
/

Luego devuelves los resultados, usarás:

variable x refcursor
exec dynamic_pivot_po(:x)
print x

Los resultados son los mismos con todas las versiones:

| PERSONID | OPTIONA | OPTIONB | OPTIONC |
------------------------------------------
|        1 |       1 |       1 |       0 |
|        2 |       0 |       0 |       1 |
|        3 |       0 |       1 |       0 |
|        4 |       1 |       0 |       1 |

Este sería el equivalente en la sintaxis de SQL Server. Según mi lectura de los documentos de Oracle, NULLIF y PIVOT parecen tener el mismo formato que sus parientes de SQL Server. El desafío será la lista dinámica que debe ser static a menos que haga que la consulta sea dinámica como lo demuestra Itzik, pero no tengo idea de si eso se puede traducir a P/SQL

WITH PersonOptions(PersonID, OptionId) AS
(
    SELECT 1, 'A'
    UNION ALL SELECT 1, 'B'
    UNION ALL SELECT 2, 'C'
    UNION ALL SELECT 3, 'B'
    UNION ALL SELECT 4, 'A'
    UNION ALL SELECT 4, 'C'
)
SELECT
    P.PersonId
,   NULLIF(P.A, 0) AS OptionA
,   NULLIF(P.B, 0) AS OptionB
,   NULLIF(P.C, 0) AS OptionC
FROM
    PersonOptions  PO
    PIVOT 
    (
        COUNT(PO.OptionId)
        FOR OPtionId IN (A, B, C)
    )  P;

Prefiero pivotar la consulta manualmente, pero puede usar PIVOT también.

SELECT PersonID,
MAX(CASE WHEN OptionId ='A' THEN 1 END) AS OptionA,
MAX(CASE WHEN OptionId ='B' THEN 1 END) AS OptionB, 
MAX(CASE WHEN OptionId ='C' THEN 1 END) AS OptionC
FROM PersonOptions
GROUP BY PersonID

valoraciones y reseñas

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *