Simple query works fine:
SELECT json_array_elements_text('["first", "third", "second"]'::json)
But I also want to retrieve array keys somehow so the output would be like:
key value 0 first 1 third 2 second
UPD
Seems like row_number() is a p̶r̶o̶p̶e̶r̶ solution, but I cannot figure out how to use it further.
Lets say i have ‘posts’ table, each post contains an array of related comments in JSON format:
SELECT id, title, comments FROM posts id title comments 1 Title 1 ["comment 1", "comment 2"] 2 Title 2 ["comment 3", "comment 4", "comment 5"] 3 Title 3 ["comment 6"]
The goal is to expand not only comments values, but also the keys:
Tricky SQL here id title comment key 1 Title 1 comment 1 0 1 Title 1 comment 2 1 2 Title 2 comment 3 0 2 Title 2 comment 4 1 2 Title 2 comment 5 2 3 Title 3 comment 6 0
UPD2
Solution using row_numbers():
SELECT *, row_number() OVER (PARTITION BY id) - 1 AS key FROM ( SELECT id, title, json_array_elements_text(comments::json) AS comment FROM posts ) p
Thanks in advance!
Advertisement
Answer
Use the function json_array_elements_text()
with ordinality:
with my_table(id, title, comments) as ( values (1, 'Title 1', '["comment 1", "comment 2"]'::json), (2, 'Title 2', '["comment 3", "comment 4", "comment 5"]'), (3, 'Title 3', '["comment 6"]') ) select id, title, value as comment, ordinality- 1 as key from my_table cross join json_array_elements_text(comments) with ordinality id | title | comment | key ----+---------+-----------+----- 1 | Title 1 | comment 1 | 0 1 | Title 1 | comment 2 | 1 2 | Title 2 | comment 3 | 0 2 | Title 2 | comment 4 | 1 2 | Title 2 | comment 5 | 2 3 | Title 3 | comment 6 | 0 (6 rows)
From the documentation:
If the WITH ORDINALITY clause is specified, an additional column of type bigint will be added to the function result columns. This column numbers the rows of the function result set, starting from 1.