But how about a reverse crosstab(a.k.a. reverse pivot)? You got columns that you wanted to transpose to rows.
That is, you need to display this...
testdb-#
with p as
(
select *, firstname || ' ' || lastname as fullname
from person
)
select * from p;
person_id | lastname | firstname | nickname | favorite_number | fullname
-----------+-----------+--------------+----------+-----------------+----------------------
1 | lennon | john winston | john | | john winston lennon
2 | mccartney | james paul | paul | | james paul mccartney
3 | harrison | george | | | george harrison
4 | starr | richard | ringo | 10 | richard starr
(4 rows)
...as this:
person_id | field | value
-----------+-----------------+----------------------
1 | favorite_number |
1 | firstname | john winston
1 | fullname | john winston lennon
1 | lastname | lennon
1 | nickname | john
1 | person_id | 1
2 | favorite_number |
2 | firstname | james paul
2 | fullname | james paul mccartney
2 | lastname | mccartney
2 | nickname | paul
2 | person_id | 2
3 | favorite_number |
3 | firstname | george
3 | fullname | george harrison
3 | lastname | harrison
3 | nickname |
3 | person_id | 3
4 | favorite_number | 10
4 | firstname | richard
4 | fullname | richard starr
4 | lastname | starr
4 | nickname | ringo
4 | person_id | 4
(24 rows)
On other RDBMS, you got to do this query:
with p as
(
select *, firstname || ' ' || lastname as fullname
from person
)
select
person_id,
'firstname' as field,
firstname as value
from p
union all
select
person_id,
'firstname' as field,
firstname as value
from p
union all
select
person_id,
'lastname' as field,
firstname as value
from p
union all
select
person_id,
'nickname' as field,
nickname as value
from p
union all
select
person_id,
'fullname' as field,
fullname as value
from p
union all
select
person_id,
'favorite_number' as field,
favorite_number::text as value
from p
order by person_id, field
That's very tedious.
If you are using Postgres, luckily there is a better way:
with p as
(
select *, firstname || ' ' || lastname as fullname
from person
)
select
person_id,
skeys(hstore(p)) as field, svals(hstore(p)) as value
from p
order by person_id, field
That's more maintainable, even if you add another column on the main query, your key value pair query need not be modified.
There's another approach (darn, PostgreSQL is too flexible! :D)
with p as
(
select *, firstname || ' ' || lastname as fullname
from person
)
select
p.person_id,
unnest(array['person_id', 'favorite_number', 'firstname','fullname','lastname', 'nickname']) as field_label,
unnest(array[cast(p.person_id as text), cast(p.favorite_number as text), p.firstname, p.fullname, p.lastname, p.nickname]) as field_value
from p
order by p.person_id, field_label
That's it folks. Happy Computing! ツ
Data Source:
create table person
(
person_id serial not null primary key,
lastname text not null,
firstname text not null,
nickname text null,
favorite_number int null
);
insert into person(lastname,firstname,nickname, favorite_number) values
('lennon','john winston','john',default),
('mccartney','james paul','paul',default),
('harrison','george',default,default),
('starr','richard','ringo', 10);
No comments:
Post a Comment