Basics for crosstab()
If you are unfamiliar with crosstab(), read this first:
Special difficulty
There are two complications here:
Involved data types are inhomogeneous. (Makes me want to inspect your database design.) The common ground is to cast involved columns to text
.
You are mixing cross-tabulation with it's opposite (sometimes called "unpivot").
Building on a slightly simplified table:
CREATE TEMP TABLE view1(
id int
, a int
, b text
, c text
);
I see two basic routes:
Route 1
First unpivot a, b, c into this form. Using the Postgres-specific unnest()
in parallel. Explanation here:
SELECT id
, unnest('{a,b,c}'::text[]) || rn AS key
, unnest(ARRAY[a::text, b::text, c::text]) AS val
FROM (
SELECT *, row_number() OVER (PARTITION BY id) AS rn -- ORDER BY ??
FROM view1
) v;
Assuming there can only at most two rows for each id value. It's undefined how you determine "first" and "second". Result (using your test data):
id key val
1 a1 25
1 b1 AA
1 c1 1C
2 a1 50
2 b1 BB
2 c1 1C
2 a2 12
2 b2 AA
2 c2 2C
3 a1 27
3 b1 BB
3 c1 2C
3 a2 87
3 b2 AA
3 c2 3C
SQL Fiddle.
The rest is not possible on sqlfiddle.com, since the additional module tablefunc
is not installed.
Feed this query to a standard crosstab()
call. Plus, You might want to cast a1
and a2
back to bigint
(or just int
?) in the outer SELECT
:
SELECT id, a1::bigint, b1, c1, a2::bigint, b2, c2 -- or just SELECT *
FROM crosstab(
$$
SELECT id
,unnest('{a,b,c}'::text[]) || rn
,unnest(ARRAY[a::text, b::text, c::text])
FROM (
SELECT *, row_number() OVER (PARTITION BY id) AS rn
FROM view1
) v
$$
, $$SELECT unnest('{a1,b1,c1,a2,b2,c2}'::text[])$$
) AS t (id varchar, a1 text, b1 text, c1 text, a2 text, b2 text, c2 text);
Voilá.
For a more dynamic solution, combine these answers:
Route 2
Run crosstab for a
, b
and c
separately and join the derived tables on id
.