К сожалению, в синтаксисе SQL не предусмотрено выражение «все столбцы, кроме этого одного столбца» . Вы можете достичь своей цели, изложив оставшийся список столбцов в выражении типа строки :
SELECT a.id, a.name
, json_agg((b.col1, b.col2, b.col3)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
Это коротко для более явной формы: . ROW
(b.col1, b.col2, b.col3)
Однако имена столбцов не сохраняются в выражениях типа строки. Таким образом вы получаете общие имена ключей в объекте JSON. Я вижу 3 варианта сохранения оригинальных имен столбцов:
1. Приведение к зарегистрированному типу
Приведение к известному (зарегистрированному) типу строки. Тип регистрируется для каждой существующей таблицы или представления или с явным CREATE TYPE
оператором. Вы можете использовать временную таблицу для специального решения (действует в течение всего сеанса):
CREATE TEMP TABLE x (col1 int, col2 text, col3 date); -- use adequate data types!
SELECT a.id, a.name
, json_agg((b.col1, b.col2, b.col3)::x) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
2. Используйте подвыбор
Используйте вложенный выбор для построения производной таблицы и ссылки на таблицу в целом . Это также несет имена столбцов. Это более многословно, но вам не нужен зарегистрированный тип:
SELECT a.id, a.name
, json_agg((SELECT x FROM (SELECT b.col1, b.col2, b.col3) AS x)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
SELECT a.id, a.name
, json_agg(json_build_object('col1', b.col1, 'col2', b.col2, 'col3', b.col3)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
Связанный:
Аналогично для jsonb
соответствующих функций jsonb_agg()
и jsonb_build_object()
.
Для Postgres 9.5 или более поздней версии также увидеть ответ a_horse в с новым вариантом короче синтаксис: Postgres добавлен оператор минус -
дляjsonb
сказать «все клавиши , кроме этого одного ключа» .
Поскольку Postgres 10 «кроме нескольких ключей» реализован с тем же оператором, text[]
что и второй операнд - как в комментариях к MLT.
Начиная с 9.6, вы можете просто использовать
-
для удаления ключа из JSONB:to_jsonb(b)
преобразует всю строку и- 'item_id'
затем удаляет ключ с именем,item_id
результат которого затем агрегируется.источник
json_agg
функцией:function json_agg(record) does not exist
Вы можете сделать это без группировки, используя подзапросы
возвращается
Эта статья от Джона Аттена действительно интересна и имеет больше деталей
источник
Я обнаружил, что лучше всего создать JSON, а затем агрегировать его. например
Обратите внимание, что это можно сделать как подзапрос, если вам не нравятся CTE (или у вас проблемы с производительностью из-за его использования).
Также обратите внимание, что если вы собираетесь много заниматься этим, может быть полезно создать функцию для переноса пар ключ-значение, чтобы код выглядел чище. Вы передадите свою функцию (например),
'ecks', 'x'
и она вернется"ecks": "x"
.источник
Хотя до сих пор нет способа сделать что-либо с выделением всех столбцов, кроме одного бита, но вы можете использовать
json_agg(to_json(b.col_1, b.col_2, b.col_3 ...))
для получения массива json jsons в каждом формате{"col_1":"col_1 value", ...}
.Таким образом, запрос будет выглядеть примерно так:
и будет возвращать строки как:
(Я сейчас на Postgres 9.5.3 и не уверен на 100%, когда эта поддержка была добавлена.)
источник
Вы можете использовать
json_build_object
как этоисточник