I have a table with 32 columns whose primary key is play_id and my goal is to create a key value pair table where the output would look like this:
x
play_id, field_name, field_value
play_id_1, game_date, ‘2020-07-23’
play_id_1, possession, ‘home’
' ', ' ', ' '
play_id_2, game_date, ‘2020-07-24’
play_id_2, possession, ‘away’
where all the entries in field_name are columns from the original table (besides play_id). So there would be 31 appearances of play_id_1 in this new table. I want the new primary key for this table to be (play_id, field_name). There’s a long way of doing it where I can query for play_id and each column and union everything together, but I want to find a more elegant solution.
Advertisement
Answer
You can use a lateral join for that. But you will need to cast all values to text
.
select t.play_id, x.*
from the_table t
cross join lateral (
values
('game_date', game_date::text),
('possession', possession::text),
('col_3', col_3::text),
) as x(field_name, field_value);
Another option is to convert the row to a JSON value and then unnest that json:
select t.play_id, x.*
from the_table t
cross join lateral jsonb_each(to_jsonb(t) - 'play_id') as x(field_name, field_value);