How to join and transpose row to columns in redshift
I have following table1
and its unique key is type
type age
A 20
B 21
C 22
And I have following result table. I'd like to join them as
type score
A 10
A 20
A 30
B 40
B 50
following transposed form.
type age score score score
A 20 10 20 30
B 21 40 50 na
C 22 na na na
Are there any way to achieve this?
select *
from table1
left join table2 usint(type)
Didn't transpose rows. If someone has opinion please let me know thanks
Solution 1:
If you don't know in advance the number of score
values per type, then you need a full dynamic solution :
First we create a composite type new_type
according to the maximum number of score
values per type in table2
. This composite type is then used for naming the columns in the final query.
CREATE OR REPLACE PROCEDURE new_type() LANGUAGE plpgsql AS
$$
DECLARE
column_txt text ;
BEGIN
SELECT string_agg(' score' || id || ' integer', ',')
INTO column_txt
FROM
( SELECT count(*) AS count
FROM table2
GROUP BY type
ORDER BY 1 DESC
LIMIT 1
) AS a
CROSS JOIN LATERAL generate_series(1, a.count :: integer) AS id ;
EXECUTE 'DROP TYPE IF EXISTS new_type' ;
EXECUTE 'CREATE TYPE new_type AS (' || column_txt || ')' ;
END ;
$$ ;
CALL new_type() ;
Then this query will provide the expected result :
SELECT c.type, c.age
, (jsonb_populate_record( NULL :: new_type
, jsonb_object_agg('score' || c.id, c.score ORDER BY c.score)
)).*
FROM
( SELECT a.type, a.age, b.score, row_number() OVER (PARTITION BY a.type, a.age ORDER BY b.score) AS id
FROM table1 AS a
LEFT JOIN table2 AS b
ON a.type = b.type
) AS c
GROUP BY c.type, c.age
ORDER BY c.type, c.age
The test result is in dbfiddle.