У нас есть документация официальный, которая мне непонятна без примеров.
У меня есть JSON, который хранит эту структуру, она немного больше, но такая же структура, больше JSON внутри массива:
WITH
responses AS (
SELECT *
FROM (VALUES ((1,
'[
{
"id": "13",
"alias": "r1",
"title": "quest",
"answer": "5",
"question": "qq",
"answer_id": 10048
},
{
"id": "24",
"alias": "q6",
"title": "quest",
"answer": "yes",
"question": "quest",
"answer_id": 10094
}
]' :: JSON),
(2,
'[
{
"id": "13",
"alias": "r1",
"title": "quest",
"answer": "-1",
"question": "qq",
"answer_id": 10048
},
{
"id": "24",
"alias": "q6",
"title": "quest",
"answer": "no",
"question": "quest",
"answer_id": 10094
}
]' :: JSON))
) TEST(id,val)
)
SELECT * from responses
Я мог преобразовать в плоскую структуру:
id| question| answer
-----------
1, 'r1', 5
1, 'q6', yes
2, 'r1', -1
2, 'q6', no
Но мне нужно таким образом получить результат
id| r1| q6
----------
1, 5, yes
2, -1, no
Как я могу получить результат, подобный предыдущему?

Есть некоторые проблемы с вашим запросом WITH.
Во-первых, нет необходимости выполнять «select * from (values (..))» - VALUES - это сам запрос, который можно использовать без SELECT:
test=# values (1, 'zz'), (2, 'bbb');
column1 | column2
---------+---------
1 | zz
2 | bbb
(2 rows)
Далее возникает проблема со скобками. Сравните предыдущий запрос с этим:
test=# values ((1, 'zz'), (2, 'bbb'));
column1 | column2
---------+---------
(1,zz) | (2,bbb)
(1 row)
Если вы поместите дополнительные круглые скобки, как это, у вас будет только одна строка из двух столбцов, а значения в этих столбцах относятся к «анонимному» типу записи (его магия типа Postgres, очень мощная, но это другая история, здесь не нужна).
Итак, давайте исправим первую часть вашего CTE:
with responses(id, val) AS (
values
(1, '
[
{
"id": "13",
"alias": "r1",
"title": "quest",
"answer": "5",
"question": "qq",
"answer_id": 10048
},
{
"id": "24",
"alias": "q6",
"title": "quest",
"answer": "yes",
"question": "quest",
"answer_id": 10094
}
]'::json
), (2, '
[
{
"id": "13",
"alias": "r1",
"title": "quest",
"answer": "-1",
"question": "qq",
"answer_id": 10048
},
{
"id": "24",
"alias": "q6",
"title": "quest",
"answer": "no",
"question": "quest",
"answer_id": 10094
}
]'::json
)
)
select * from responses;
Теперь мы можем использовать функцию json_array_elements (..) для извлечения элементов JSON из массивов JSON:
with responses(id, val) AS (
values
...
)
select id, json_array_elements(val)
from responses;
Давайте воспользуемся им для построения «второй ступени» нашего CTE:
...
), extra(id, elem) as (
select id, json_array_elements(val)
from responses
)
...
И, наконец, мы получим такой результат:
...
select
id,
elem->>'id' as json_id,
elem->>'alias' as alias,
elem->>'question' as question,
elem->>'answer' as answer
from extra;
Весь запрос:
with responses(id, val) AS (
values
(1, '
[
{
"id": "13",
"alias": "r1",
"title": "quest",
"answer": "5",
"question": "qq",
"answer_id": 10048
},
{
"id": "24",
"alias": "q6",
"title": "quest",
"answer": "yes",
"question": "quest",
"answer_id": 10094
}
]'::json
), (2, '
[
{
"id": "13",
"alias": "r1",
"title": "quest",
"answer": "-1",
"question": "qq",
"answer_id": 10048
},
{
"id": "24",
"alias": "q6",
"title": "quest",
"answer": "no",
"question": "quest",
"answer_id": 10094
}
]'::json
)
), extra(id, elem) as (
select id, json_array_elements(val)
from responses
)
select
id as row_id,
elem->>'id' as json_id,
elem->>'alias' as alias,
elem->>'question' as question,
elem->>'answer' as answer
from extra;
Результат:
row_id | id | alias | question | answer
--------+----+-------+----------+--------
1 | 13 | r1 | qq | 5
1 | 24 | q6 | quest | yes
2 | 13 | r1 | qq | -1
2 | 24 | q6 | quest | no
(4 rows)
Это немного отличается от того, что вы хотели. То, что вы хотели, не может быть достигнуто с помощью чистого SQL, поскольку вы хотите иметь динамические имена столбцов в выходных данных - эти «r1» и «q6» должны динамически извлекаться из данных JSON. Однако с помощью plpgsql или с расширением tablefunc можно создать сводную таблицу, дайте мне знать, если вам это нужно.
вы не можете этого достичь без поворота? Получить имя столбца не проблема, можно жестко запрограммировать?
Конечно, если вы можете жестко запрограммировать имена столбцов, вы легко сможете сделать это с помощью обычного sql.
Но как? без поворота
С участием. Но без расширений tapoueh.org/blog/2013/07/simple-case-for-pivoting-in-sql
См. stackoverflow.com/a/23061730/50552, чтобы узнать, как превратить строки в столбцы.