Within my Postgres database, I have a column (type=JSONB) that contains an API response that represents someone response to a Survey Monkey survey. Within this JSON object, there is an array called pages
that contains at least 1 item, and something more than 1 item. Then within pages
, there is another array called questions
. This array also contains at least 1 item, and more often more than 1 item.
I am trying to write a Postgres query to extract the responses from all the questions seen within pages
and questions
. The final format should be 1 record per question. If the survey has 5 questions, that would create 5 rows. If the survey has 100 questions, across 5 pages, that would mean 100 rows.
──────────── ──────────────────────────────────────────── ──────────────────────
| id | heading | simple_text |
──────────── ──────────────────────────────────────────── ──────────────────────
| 775249149 | I am confident that I am the best. | Somewhat Agree |
| 775249153 | I currently have the skills to be amazing | Somewhat Agree |
| 775249166 | How long until I win the lottery? | 6 to 12 months more |
──────────── ──────────────────────────────────────────── ──────────────────────
I've been trying to use the function json_array_elements
, but I'm experiencing some errors when trying to pass in an array-of-arrays.
{
"id": "12345",
"href": "https://api.surveymonkey.com",
"pages": [
{
"id": "142250690",
"questions": [
{
"id": "775249149",
"family": "matrix",
"answers": [
{
"row_id": "5133514018",
"choice_id": "5133514023",
"simple_text": "Somewhat Agree",
"choice_metadata": {
"weight": "5"
}
}
],
"heading": "I am confident that I am the best.",
"subtype": "rating"
},
{
"id": "775249153",
"family": "matrix",
"answers": [
{
"row_id": "5133514112",
"choice_id": "5133514117",
"simple_text": "Somewhat Agree",
"choice_metadata": {
"weight": "5"
}
}
],
"heading": "I currently have the skills to be amazing",
"subtype": "rating"
},
{
"id": "775249166",
"family": "matrix",
"answers": [
{
"row_id": "5133514278",
"choice_id": "5133514280",
"simple_text": "6 to 12 months more",
"choice_metadata": {
"weight": "2"
}
}
],
"heading": "How long until I win the lottery?",
"subtype": "rating"
}
]
}
],
"survey_id": "123456789",
"total_time": 29,
"date_created": "2022-07-25T23:08:36 00:00",
"recipient_id": "",
"date_modified": "2022-07-25T23:09:06 00:00",
"email_address": "",
"collection_mode": "default",
"response_status": "completed",
}
CodePudding user response:
Try to use json_array_elements()
twice:
http://sqlfiddle.com/#!17/9eecb/94455
select v->'id', v->'heading', v->'subtype', v->'answers'->0->'simple_text' from (
select json_array_elements(value->'questions')::jsonb as v from json_array_elements('{
"id": "12345",
"href": "https://api.surveymonkey.com",
"pages": [
{
"id": "142250690",
"questions": [
{
"id": "775249149",
"family": "matrix",
"answers": [
{
"row_id": "5133514018",
"choice_id": "5133514023",
"simple_text": "Somewhat Agree",
"choice_metadata": {
"weight": "5"
}
}
],
"heading": "I am confident that I am the best.",
"subtype": "rating"
},
{
"id": "775249153",
"family": "matrix",
"answers": [
{
"row_id": "5133514112",
"choice_id": "5133514117",
"simple_text": "Somewhat Agree",
"choice_metadata": {
"weight": "5"
}
}
],
"heading": "I currently have the skills to be amazing",
"subtype": "rating"
},
{
"id": "775249166",
"family": "matrix",
"answers": [
{
"row_id": "5133514278",
"choice_id": "5133514280",
"simple_text": "6 to 12 months more",
"choice_metadata": {
"weight": "2"
}
}
],
"heading": "How long until I win the lottery?",
"subtype": "rating"
}
]
},
{
"id": "142250690",
"questions": [
{
"id": "775249199",
"family": "matrix",
"answers": [
{
"row_id": "5133514278",
"choice_id": "5133514280",
"simple_text": "6 to 12 months more",
"choice_metadata": {
"weight": "2"
}
}
],
"heading": "qweqweqweqwqqqq?",
"subtype": "rating"
}
]
}
],
"survey_id": "123456789",
"total_time": 29,
"date_created": "2022-07-25T23:08:36 00:00",
"recipient_id": "",
"date_modified": "2022-07-25T23:09:06 00:00",
"email_address": "",
"collection_mode": "default",
"response_status": "completed"
}'::jsonb::json->'pages')
) t;
UPDATE
If you need to process data from table contained described json rows, you need something like this: