Rows to Columns

Transposing One to One

This topic demonstrates how to take values like those under the VAL column below

GROUP_KEY  PIVOT_KEY  VAL
---------- ---------- ----------
G0         P0         a
G0         P1         A
G0         P2         1
G0         (null)     xyz

G1         P0         b
G1         P1         B
G1         P2         (null)

(null)     P0         c
(null)     P2         3
(null)     (null)     (null)
 

and arrange them in a matrix like this (also known as a "crosstab report" or "pivot table").

GROUP_KEY  P0         P1         P2         UNASSIGNED
---------- ---------- ---------- ---------- ----------
G0         a          A          1          xyz
G1         b          B
(null)     c                     3
 

In this scenario there is only one VAL value for each distinct (GROUP_KEY, PIVOT_KEY) pair.

11g PIVOT Solution

A PIVOT query like the ones presented in Aggregating Values (11g) can be used with the aggregate functions MAX or MIN to transpose rows to columns

column group_key null '(null)'

select
  group_key ,
  p0 ,
  p1 ,
  p2 ,
  unassigned
from
  ( select group_key, nvl(pivot_key,'%') as pivot_key, val from t1 ) pivot
    ( MAX(val)
      for pivot_key in
        (
          'P0' as p0 ,
          'P1' as p1 ,
          'P2' as p2 ,
          '%'  as unassigned
        )
    )
order by
  group_key
;
 
GROUP_KEY  P0         P1         P2         UNASSIGNED
---------- ---------- ---------- ---------- ----------
G0         a          A          1          xyz
G1         b          B
(null)     c                     3
 

All Versions

A slightly more compact solution that works in any version of Oracle can be constructed using the MAX query presented in Aggregating Values.

select
  group_key ,
  max( decode( pivot_key, 'P0', val, null ) ) as p0 ,
  max( decode( pivot_key, 'P1', val, null ) ) as p1 ,
  max( decode( pivot_key, 'P2', val, null ) ) as p2 ,
  max( decode( pivot_key, null, val, null ) ) as unassigned
from t1
group by group_key
order by group_key
;
 
GROUP_KEY  P0         P1         P2         UNASSIGNED
---------- ---------- ---------- ---------- ----------
G0         a          A          1          xyz
G1         b          B
(null)     c                     3
 

Note that MAX could be replaced with MIN and the results would still be the same since the DECODE logic ensures there is only one non-null value per group per column.

select
  group_key ,
  MIN( decode( pivot_key, 'P0', val, null ) ) as p0 ,
  MIN( decode( pivot_key, 'P1', val, null ) ) as p1 ,
  MIN( decode( pivot_key, 'P2', val, null ) ) as p2 ,
  MIN( decode( pivot_key, null, val, null ) ) as unassigned
from t1
group by group_key
order by group_key
;
 
GROUP_KEY  P0         P1         P2         UNASSIGNED
---------- ---------- ---------- ---------- ----------
G0         a          A          1          xyz
G1         b          B
(null)     c                     3
 



Linking to SQL Snippets ™

To link to this page in Oracle Technology Network Forums or OraFAQ Forums cut and paste this code.

  • [url=http://www.sqlsnippets.com/en/topic-12186.html]SQL Snippets: Rows to Columns - Transposing One to One[/url]

To link to this page in HTML documents or Blogger comments cut and paste this code.

  • <a href="http://www.sqlsnippets.com/en/topic-12186.html">SQL Snippets: Rows to Columns - Transposing One to One</a>

To link to this page in other web sites use the following values.

  • Link Text : SQL Snippets: Rows to Columns - Transposing One to One
  • URL (href): http://www.sqlsnippets.com/en/topic-12186.html