#arrays #json #postgresql #postgresql-9.6
#массивы #json #postgresql #postgresql-9.6
Вопрос:
У меня есть следующая таблица :
id | model | version | status
_________________________________________
.. | model1 | 1.0 | old
.. | model1 | 2.0 | new
.. | model2 | 1.1 | old
.. | model2 | 1.2 | new
Мне нужно сгенерировать объект JSON на основе статуса для той же модели (объединить две строки в один объект JSON), как показано ниже :
[
{
"model" : "model1",
"old_version" : "1.0",
"new_version" : "2.0"
},
{
"model" : "model2",
"old_version" : "1.1",
"new_version" : "1.2"
}
]
Что я пробовал до сих пор :
select json_agg(json_build_object(t."model",
CASE WHEN t."status" == 'new'
THEN 'new_version',t."version",
end
CASE WHEN t."status" == 'old'
THEN 'old_version',t."version",
end ))
from (// my select query with various conditions goes here) t
Я также получаю синтаксическую ошибку. Как я могу добиться ожидаемого результата
Заранее благодарю!!
Ответ №1:
THEN
Часть выражения CASE может содержать только одно выражение, поэтому then value_a, value_b end
недопустима. Вам также не хватает ключа для model
значения.
Однако здесь у вас есть двухэтапная агрегация: сначала агрегируйте версии для каждой модели, затем агрегируйте этот результат в массив. Поскольку агрегатные функции не могут быть вложенными, для этого вам нужна производная таблица:
Это объединяет версии для каждой модели:
select jsonb_build_object('model', model)||jsonb_object_agg(status||'_version', version)
from (...)
group by model
Если вы не можете или не хотите использовать имя состояния в качестве префикса для «ключа версии», вам придется использовать выражение CASE:
select jsonb_build_object('model', model)||
jsonb_object_agg(case status
when 'old' then 'old_version'
when 'new' then 'new_version'
end,
version)
from (...)
group by model
Затем это можно использовать в производной таблице для получения массива json:
select jsonb_agg(model)
from (
select jsonb_build_object('model', model)||jsonb_object_agg(status||'_version', version) as model
from (...)
group by model
) t
Комментарии:
1. Поскольку вы использовали оператор OR, не даст ли он два объекта JSON для каждой модели? Мне нужен один объект JSON со значениями версии и значением модели
2. @code-geek: я не понимаю, что вы имеете в виду. В моем запросе нет ИЛИ.
3. я имею в виду, что я не получаю ожидаемый массив JSON. Он добавляет дополнительный ключ в качестве модели, а значением является объект JSON с тремя ключами. Вместо этого я хочу массив с прямым объектом JSON с тремя ключами
4. Пожалуйста, посмотрите Онлайн-пример, он возвращает именно то значение, которое вы хотите
5. Это запрос, который я сформулировал. Объекты JSON создаются, как и ожидалось, но я сталкиваюсь с проблемой (добавлен дополнительный ключ) при выполнении агрегирования. Пожалуйста, помогите мне, где я делаю неправильно