patternMajor
Pivot rows into multiple columns
Viewed 0 times
rowscolumnsintopivotmultiple
Problem
I have a SQL Server instance that has a linked server to an Oracle server. There is a table on the Oracle server called
I need to pivot that data so the results are:
Any suggestions?
PersonOptions which contains the following data:╔══════════╦══════════╗
║ PersonID ║ OptionID ║
╠══════════╬══════════╣
║ 1 ║ A ║
║ 1 ║ B ║
║ 2 ║ C ║
║ 3 ║ B ║
║ 4 ║ A ║
║ 4 ║ C ║
╚══════════╩══════════╝
I need to pivot that data so the results are:
╔══════════╦═════════╦══════════╦══════════╗
║ PersonID ║ OptionA ║ Option B ║ Option C ║
╠══════════╬═════════╬══════════╬══════════╣
║ 1 ║ 1 ║ 1 ║ ║
║ 2 ║ ║ ║ 1 ║
║ 3 ║ ║ 1 ║ ║
║ 4 ║ 1 ║ ║ 1 ║
╚══════════╩═════════╩══════════╩══════════╝
Any suggestions?
Solution
There are a few ways that you can perform this data transformation. You have access to the
Aggregate /Case version:
See SQL Fiddle with Demo
Static Pivot:
See SQL Fiddle with Demo
Dynamic Version:
The two versions above work great if you have a known number of values, but if your values are unknown, then you will want to implement dynamic sql and in Oracle you can use a procedure:
Then you return the results, you will use:
The results are the same with all versions:
PIVOT function then that will be the easiest, but if not then you can use an aggregate function and a CASE.Aggregate /Case version:
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;See SQL Fiddle with Demo
Static Pivot:
select *
from
(
select personid, optionid
from PersonOptions
) src
pivot
(
count(optionid)
for optionid in ('A' as OptionA, 'B' OptionB, 'C' OptionC)
) piv
order by personidSee SQL Fiddle with Demo
Dynamic Version:
The two versions above work great if you have a known number of values, but if your values are unknown, then you will want to implement dynamic sql and in Oracle you can use a procedure:
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;
/Then you return the results, you will use:
variable x refcursor
exec dynamic_pivot_po(:x)
print xThe results are the same with all versions:
| PERSONID | OPTIONA | OPTIONB | OPTIONC |
------------------------------------------
| 1 | 1 | 1 | 0 |
| 2 | 0 | 0 | 1 |
| 3 | 0 | 1 | 0 |
| 4 | 1 | 0 | 1 |Code Snippets
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;select *
from
(
select personid, optionid
from PersonOptions
) src
pivot
(
count(optionid)
for optionid in ('A' as OptionA, 'B' OptionB, 'C' OptionC)
) piv
order by personidCREATE 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;
/variable x refcursor
exec dynamic_pivot_po(:x)
print x| PERSONID | OPTIONA | OPTIONB | OPTIONC |
------------------------------------------
| 1 | 1 | 1 | 0 |
| 2 | 0 | 0 | 1 |
| 3 | 0 | 1 | 0 |
| 4 | 1 | 0 | 1 |Context
StackExchange Database Administrators Q#30119, answer score: 22
Revisions (0)
No revisions yet.