I am trying to explode/unnest a row of jsonb arrays into individual rows and keep any rows that would result in nulls.
Fiddle: https://www.db-fiddle.com/f/pgd6E5yKf8NzPtgboeoC6c/7
Input table: (I am stuck with the input being in this form)
id | name | color | price | description |
---|---|---|---|---|
1 | ["Banana"] | [["Green"]] | [[[1]]] | [[["Good"]]] |
2 | ["Banana"] | [["Yellow"]] | [[[]]] | [[[]]] |
3 | ["Apple","Carrot"] | [["Red"],["Orange"]] | [[[10]],[[14]]] | [[["Round"]],[["Long"]]] |
4 | ["Grape","Pineapple"] | [["Green"],["Brown","Pink"]] | [[[2]],[[13],[29]]] | [[["Small"]],[["Short"],["Tall"]]] |
5 | ["Orange","Potato"] | [["Orange"],["Purple","Brown"]] | [[[2]],[[9],[]]] | [[["Bright"]],[["Gross"],[]]] |
Desired Output:
id | name | color | price | description |
---|---|---|---|---|
1 | Banana | Green | 1 | Good |
2 | Banana | Yellow | null | null |
3 | Apple | Red | 10 | Round |
3 | Carrot | Orange | 14 | Long |
4 | Grape | Green | 2 | Small |
4 | Pineapple | Brown | 13 | Short |
4 | Pineapple | Pink | 29 | Tall |
5 | Orange | Orange | 2 | Bright |
5 | Potato | Purple | 9 | Gross |
5 | Potato | Brown | null | null |
I can get the output I want with this query, but I am trying to generate these queries using a templating engine and I'm trying to account for any number of elements being any depth of nested arrays. Trying to template this to handle that will be less than ideal.
-- Gives expected results
WITH first_level AS (
SELECT
id,
jsonb_array_elements(name) AS name,
jsonb_array_elements(color) AS color,
jsonb_array_elements(price) AS price,
jsonb_array_elements(description) AS description
FROM food
),
second_level AS (
SELECT
id,
name,
jsonb_array_elements(color) AS color,
jsonb_array_elements(price) AS price,
jsonb_array_elements(description) AS description
FROM first_level
)
SELECT
id,
name,
color,
CASE
WHEN price = '[]'::jsonb THEN null
ELSE jsonb_array_elements(price)
END AS price,
CASE
WHEN description = '[]'::jsonb THEN null
ELSE jsonb_array_elements(description)
END AS description
FROM second_level
I've tried unnesting them all at once but with pg 9.6 that gives back a bad result and doesnt have the nulls, It works better on pg10+ but it still drops the rows with empty arrays.
Is there a cleaner way to achieve this result? I've run across examples of using lateral joins but none of them are exact matches and I cant figure them out to even get a result close to what I need.
Thanks