When running this query:
SELECT id,col1,col2
FROM app_data.content_cards
I get a table like this:
---- ------------------------------- --------
| id | col1 | col2 |
---- ------------------------------- --------
| 90 | {'one', 'two', 'three'} | {1,2,3}|
---- ------------------------------- --------
| 91 | {'abc', 'def'} | {1,2} |
---- ------------------------------- --------
| 92 | {'asdf} | {1} |
---- ------------------------------- --------
What I want to do now is get this same information but with the arrays splitted into rows so I get a result like this:
---- --------------------- -------
| id | col1 | col2 |
---- --------------------- -------
| 90 | one | 1 |
---- --------------------- -------
| 90 | two | 2 |
---- --------------------- -------
| 90 | three | 3 |
---- --------------------- -------
| 91 | abc | 1 |
---- --------------------- -------
| 91 | def | 2 |
---- --------------------- -------
| 92 | asdf | 1 |
---- --------------------- -------
As you can see I don't want to get rows with null value in "col1" and "col2".
Many thanks!
CodePudding user response:
Assuming col1 and col2 got the same number of elements , you can make a view with the UNNEST function to split it and then query it.
WITH unnested_col1 AS (
SELECT id, unnest(col1) as col1, ROW_NUMBER() OVER (PARTITION BY id ORDER BY unnest(col1)) as row_num
FROM app_data.content_cards
), unnested_col2 AS (
SELECT id, unnest(col2) as col2, ROW_NUMBER() OVER (PARTITION BY id ORDER BY unnest(col2)) as row_num
FROM app_data.content_cards
)
SELECT unnested_col1.id, unnested_col1.col1, unnested_col2.col2
FROM unnested_col1
JOIN unnested_col2 ON unnested_col1.id = unnested_col2.id AND unnested_col1.row_num = unnested_col2.row_num
CodePudding user response:
We can use UNNEST
on both columns:
SELECT id,
UNNEST(col1) AS col1,
UNNEST(col2) AS col2
FROM content_cards
ORDER BY id;
See the documentation
Try out here: db<>fiddle
CodePudding user response:
To make sure that matching array entries wind up on the same row, pass both arrays to a single unnest() call:
SELECT c.id, u.*
FROM content_cards c
cross join unnest(col1, col2) as u(col1, col2)
ORDER BY id;
This guarantees that elements from matching array positions wind up in the same row even if one array has a different number of elements (the missing ones will be filled with null
values).
If it's possible that some arrays have not elements at all but you still want to see the id
of the base table, use an outer join:
FROM content_cards c
left join unnest(col1, col2) as u(col1, col2) on true