Existem algumas maneiras de executar essa transformação de dados. Você tem acesso à PIVOT
função, então será a mais fácil, mas, se não, poderá usar uma função agregada e a CASE
.
Versão 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;
Veja SQL Fiddle com demonstração
Pivô 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
Veja SQL Fiddle com demonstração
Versão dinâmica:
As duas versões acima funcionam muito bem se você tiver um número conhecido de valores, mas se seus valores forem desconhecidos, você desejará implementar o sql dinâmico e, no Oracle, poderá usar um procedimento:
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;
/
Então você retorna os resultados, você usará:
variable x refcursor
exec dynamic_pivot_po(:x)
print x
Os resultados são os mesmos com todas as versões:
| PERSONID | OPTIONA | OPTIONB | OPTIONC |
------------------------------------------
| 1 | 1 | 1 | 0 |
| 2 | 0 | 0 | 1 |
| 3 | 0 | 1 | 0 |
| 4 | 1 | 0 | 1 |
where a.personId = a2.personId order by a2.personId for xml path('')
. a2 é a tabela na subconsulta. Em seguida, separo os dados no Excel usando texto em colunas com vírgula como delimitador. Eu esperava encontrar uma maneira de fazer isso no sql regular sem precisar escrever um procedimento, mas talvez não haja nenhuma maneira. Tem que correr no momento, mas vou tentar postar um exemplo disso para explicar melhor.Isso seria o equivalente na sintaxe do SQL Server. Com base na minha leitura dos documentos do Oracle, NULLIF e PIVOT parecem ter o mesmo formato que seus parentes do SQL Server. O desafio será a lista dinâmica, que precisa ser estática, a menos que você faça a consulta dinâmica, como Itzik demonstra, mas não tenho idéia se isso pode ser traduzido para P / SQL
fonte
Prefiro dinamizar a consulta manualmente, mas você também pode usá-lo
PIVOT
.fonte
PIVOT
sintaxe é mais complicada em comparação com a abordagem que uso. No entanto, sei que os dois dão o mesmo resultado e concordo que outras pessoas possam pensar o contrário.