In Excel, we can do this using TRANSPOSE, a bit of patience & know-how, and ctrl+shift+enter.
In Oracle, if we have aggregate data displaying months by row, the old way was to use a bunch of DECODEs (or similar)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 |
SELECT t. name
, SUM (DECODE (TO_CHAR (e.start_date, 'mon' ), 'jan' ,1,0)) jan
, SUM (DECODE (TO_CHAR (e.start_date, 'mon' ), 'feb' ,1,0)) feb
, SUM (DECODE (TO_CHAR (e.start_date, 'mon' ), 'mar' ,1,0)) mar
, SUM (DECODE (TO_CHAR (e.start_date, 'mon' ), 'apr' ,1,0)) apr
, SUM (DECODE (TO_CHAR (e.start_date, 'mon' ), 'may' ,1,0)) may
, SUM (DECODE (TO_CHAR (e.start_date, 'mon' ), 'jun' ,1,0)) jun
, SUM (DECODE (TO_CHAR (e.start_date, 'mon' ), 'jul' ,1,0)) jul
, SUM (DECODE (TO_CHAR (e.start_date, 'mon' ), 'aug' ,1,0)) aug
, SUM (DECODE (TO_CHAR (e.start_date, 'mon' ), 'sep' ,1,0)) sep
, SUM (DECODE (TO_CHAR (e.start_date, 'mon' ), 'oct' ,1,0)) oct
, SUM (DECODE (TO_CHAR (e.start_date, 'mon' ), 'nov' ,1,0)) nov
, SUM (DECODE (TO_CHAR (e.start_date, 'mon' ), 'dec' ,1,0)) dec FROM events e, bookings b, resources r, resource_types t WHERE e.event_no = b.event_no AND r.code = b.resource_code AND r.type_code = t.code GROUP BY t. name ;
NAME JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC -------------------- --- --- --- --- --- --- --- --- --- --- --- --- Catering 0 0 2 1 0 0 0 0 0 0 0 0 Stationary 0 0 1 1 0 0 0 0 0 0 0 0 Video equipment 0 0 1 1 1 0 0 0 1 0 0 0 Audio equipment 0 0 0 0 0 0 0 0 0 1 0 0 Computer equipment 0 0 1 0 0 0 0 0 0 0 0 0 Locations 0 0 2 2 2 1 1 1 1 1 0 0
6 rows selected |
Oracle 11g introduced pivot queries.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 |
SELECT * FROM
( SELECT COUNT (*) c, t. name , TO_CHAR(start_date, 'mon' ) mth
FROM events e, bookings b, resources r, resource_types t
WHERE e.event_no = b.event_no
AND r.code = b.resource_code
AND r.type_code = t.code
GROUP BY t. name , to_char(start_date, 'mon' ) ) PIVOT
( SUM (c) -- Add up all my counts
FOR mth -- Transposing the months
IN ( 'jan' as jan
, 'feb' , 'mar' , 'apr' , 'may' , 'jun'
, 'jul' , 'aug' , 'sep' , 'oct' , 'nov' , 'dec' ) );
NAME JAN 'feb' 'mar' 'apr' 'may' 'jun' 'jul' 'aug' 'sep' 'oct' 'nov' 'dec' -------------------- --- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Catering 2 1 Stationary 1 1 Video equipment 1 1 1 1 Audio equipment 1 Computer equipment 1 Locations 2 2 2 1 1 1 1 1
6 rows selected |
As with most esoteric SQL functions, there are quite a few good examples on the web that I'm not out to emulate - the prime purpose of this post was to help remind me what's going on.
That being said, Tim Hall and Arup Nanda have the most concise articles.
I particularly like Lucas Jellema's example linked by Arup using
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 |
select value from (
(
select
'a' v1,
'e' v2,
'i' v3,
'o' v4,
'u' v5
from dual
)
unpivot
(
value
for value_type in
(v1,v2,v3,v4,v5)
) ) / |
출처 : http://www.grassroots-oracle.com/2012/05/oracle-pivot.html