Infelizmente, não há nenhuma disposição na sintaxe SQL para dizer "todas as colunas, exceto esta coluna" . Você pode atingir seu objetivo, digitando a lista restante de colunas em uma expressão do tipo linha :
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;
Isso é curto para a forma mais explícita: . ROW
(b.col1, b.col2, b.col3)
No entanto, os nomes das colunas não são preservados nas expressões do tipo de linha. Você obtém nomes de chaves genéricos no objeto JSON dessa maneira. Vejo três opções para preservar os nomes das colunas originais:
1. Transmitir para o tipo registrado
Transmitir para um tipo de linha conhecido (registrado). Um tipo é registrado para cada tabela ou exibição existente ou com uma CREATE TYPE
declaração explícita . Você pode usar uma tabela temporária para uma solução ad-hoc (vida útil durante a sessão):
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. Use uma subseleção
Use uma subseleção para construir uma tabela derivada e referencie a tabela como um todo . Isso também carrega nomes de colunas. É mais detalhado, mas você não precisa de um tipo registrado:
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;
Palavras-chave:
Semelhante para jsonb
com as respectivas funções jsonb_agg()
e jsonb_build_object()
.
Para Postgres 9.5 ou posterior, veja também a resposta de a_horse com uma nova variante de sintaxe mais curta: O Postgres adicionou o operador menos -
parajsonb
dizer "todas as chaves, exceto essa chave" .
Desde o Postgres 10, "exceto várias chaves", é implementado com o mesmo operador usando text[]
o 2º operando - como o mlt comentou.