Istnieje kilka sposobów przeprowadzenia tej transformacji danych. Masz dostęp do PIVOT
funkcji, to będzie najłatwiejsze, ale jeśli nie, możesz użyć funkcji agregującej i CASE
.
Wersja zbiorcza / sprawy:
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;
Zobacz SQL Fiddle with Demo
Pivot statyczny:
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
Zobacz SQL Fiddle with Demo
Wersja dynamiczna:
Dwie powyższe wersje działają świetnie, jeśli masz znaną liczbę wartości, ale jeśli twoje wartości są nieznane, to chcesz zaimplementować dynamiczne narzędzie SQL, aw Oracle możesz użyć procedury:
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;
/
Następnie zwrócisz wyniki, użyjesz:
variable x refcursor
exec dynamic_pivot_po(:x)
print x
Wyniki są takie same dla wszystkich wersji:
| 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 to tabela w podzapytaniu. Następnie rozdzielam dane w programie Excel, używając tekstu do kolumn z przecinkiem jako separatorem. Miałem nadzieję znaleźć sposób na zrobienie tego w zwykłym sql bez konieczności pisania procedury, ale może nie ma takiej możliwości. W tej chwili muszę biec, ale postaram się opublikować przykład tego, aby lepiej to wyjaśnić.Byłoby to równoważne w składni SQL Server. Na podstawie mojej lektury dokumentów Oracle wydaje się , że NULLIF i PIVOT mają ten sam format, co ich rodziny SQL Server. Wyzwaniem będzie lista przestawna, która musi być statyczna, chyba że zapytanie zostanie dynamiczne, jak pokazuje Itzik , ale nie mam pojęcia, czy można to przetłumaczyć na P / SQL
źródło
Wolę ręcznie przestawiać zapytania, ale możesz także użyć
PIVOT
.źródło
PIVOT
składnia jest bardziej skomplikowana w porównaniu do podejścia, którego używam. Wiem jednak, że oba dają ten sam rezultat i zgadzam się, że inni ludzie mogą myśleć inaczej.