Advertisement Space
Transforming rows into columns and back
Turning rows into columns (and vice versa) is a common reporting requirement. Before Oracle 11g, you had to use DECODE or CASE with GROUP BY. Now PIVOT and UNPIVOT make it much cleaner.
Recipe #1 - PIVOT rows into columns
Given a table of sales by quarter, turn each quarter into its own column:
SELECT *
FROM (
SELECT salesman, quarter, amount
FROM sales
)
PIVOT (
SUM(amount)
FOR quarter IN ('Q1' AS q1, 'Q2' AS q2, 'Q3' AS q3, 'Q4' AS q4)
)
ORDER BY salesman;
This transforms data from:
| salesman | quarter | amount |
|---|---|---|
| Alice | Q1 | 1000 |
| Alice | Q2 | 1500 |
Into:
| salesman | q1 | q2 | q3 | q4 |
|---|---|---|---|---|
| Alice | 1000 | 1500 | ... | ... |
Recipe #2 - PIVOT with multiple aggregations
You can pivot with multiple aggregate functions:
SELECT *
FROM (
SELECT deptno, job, sal
FROM emp
)
PIVOT (
COUNT(*) AS cnt,
AVG(sal) AS avg_sal
FOR job IN ('CLERK' AS clerk, 'MANAGER' AS mgr, 'ANALYST' AS analyst)
);
Recipe #3 - UNPIVOT columns into rows
UNPIVOT is the reverse — it turns columns back into rows:
SELECT *
FROM quarterly_sales
UNPIVOT (
amount FOR quarter IN (q1 AS 'Q1', q2 AS 'Q2', q3 AS 'Q3', q4 AS 'Q4')
)
ORDER BY salesman, quarter;
Recipe #4 - Pre-11g PIVOT with DECODE
If you're on an older Oracle version, use DECODE with GROUP BY:
SELECT salesman,
SUM(DECODE(quarter, 'Q1', amount, 0)) AS q1,
SUM(DECODE(quarter, 'Q2', amount, 0)) AS q2,
SUM(DECODE(quarter, 'Q3', amount, 0)) AS q3,
SUM(DECODE(quarter, 'Q4', amount, 0)) AS q4
FROM sales
GROUP BY salesman;