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.
A partir do 9.6, você pode simplesmente usar
-
para remover uma chave de um JSONB:to_jsonb(b)
converterá a linha inteira e- 'item_id'
removerá a chave com o nomeitem_id
cujo resultado será agregado.fonte
json_agg
função:function json_agg(record) does not exist
Você pode realmente fazer isso sem grupo, usando subconsultas
retorna
Este artigo de John Atten é realmente interessante e tem mais detalhes
fonte
Descobri que é melhor criar o JSON e agregá-lo. por exemplo
Observe que isso pode ser feito como uma subconsulta se você não gostar de CTEs (ou tiver problemas de desempenho por causa do uso).
Observe também que, se você fizer muito isso, pode ser benéfico criar uma função para agrupar os pares de valores-chave para você, para que o código pareça mais limpo. Você passaria sua função (por exemplo)
'ecks', 'x'
e ela retornaria"ecks": "x"
.fonte
Embora ainda não haja maneira de fazer nada sobre a seleção de todas as colunas, exceto um bit, mas você pode usar
json_agg(to_json(b.col_1, b.col_2, b.col_3 ...))
para obter uma matriz json de jsons, cada uma no formato{"col_1":"col_1 value", ...}
.Portanto, a consulta seria algo como:
e retornaria linhas como:
(Estou no Postgres 9.5.3 agora e não tenho 100% de certeza quando esse suporte foi adicionado.)
fonte
Você pode usar
json_build_object
assimfonte