Malheureusement, il n'y a aucune disposition dans la syntaxe SQL pour dire "toutes les colonnes sauf celle-ci" . Vous pouvez atteindre votre objectif en précisant la liste restante des colonnes dans une expression de type ligne :
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;
C'est court pour la forme plus explicite: . ROW
(b.col1, b.col2, b.col3)
Cependant, les noms de colonnes ne sont pas conservés dans les expressions de type ligne. Vous obtenez ainsi des noms de clé génériques dans l'objet JSON. Je vois 3 options pour conserver les noms de colonnes d'origine:
1. Cast au type enregistré
Cast sur un type de ligne bien connu (enregistré). Un type est enregistré pour chaque table ou vue existante ou avec une CREATE TYPE
instruction explicite . Vous pouvez utiliser une table temporaire pour une solution ad-hoc (vit pour la durée de la session):
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. Utilisez une sous-sélection
Utilisez une sous-sélection pour construire une table dérivée et référencer la table dans son ensemble . Cela porte également des noms de colonne. Il est plus détaillé, mais vous n'avez pas besoin d'un type enregistré:
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;
3. json_build_object()
dans Postgres 9.4 ou version ultérieure
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;
En relation:
Similaire pour jsonb
les fonctions respectives jsonb_agg()
et jsonb_build_object()
.
Pour Postgres 9.5 ou version ultérieure, voir également la réponse de a_horse avec une nouvelle variante de syntaxe plus courte: Postgres a ajouté l' opérateur moins -
pourjsonb
dire "toutes les clés sauf celle-ci" .
Étant donné que Postgres 10 "sauf plusieurs touches" est implémenté avec le même opérateur prenant text[]
comme commentaire le 2ème opérande comme mlt.
À partir de 9.6, vous pouvez simplement utiliser
-
pour supprimer une clé d'un JSONB:to_jsonb(b)
convertira toute la ligne,- 'item_id'
puis supprimera la clé avec le nom dontitem_id
le résultat est ensuite agrégé.la source
json_agg
fonction:function json_agg(record) does not exist
Vous pouvez le faire sans groupe en utilisant des sous-requêtes
Retour
Cet article de John Atten est vraiment intéressant et contient plus de détails
la source
J'ai trouvé qu'il était préférable de créer le JSON, puis de l'agréger. par exemple
Notez que cela peut être fait en tant que sous-requête si vous n'aimez pas les CTE (ou si vous rencontrez des problèmes de performances en raison de son utilisation).
Notez également que si vous allez souvent faire cela, il peut être avantageux de créer une fonction pour envelopper les paires clé-valeur pour que le code soit plus propre. Vous passeriez votre fonction (par exemple)
'ecks', 'x'
et elle reviendrait"ecks": "x"
.la source
Bien qu'il n'y ait toujours aucun moyen de faire quoi que ce soit pour sélectionner toutes les colonnes sauf un bit, mais vous pouvez utiliser
json_agg(to_json(b.col_1, b.col_2, b.col_3 ...))
pour obtenir un tableau json de jsons chacune au format{"col_1":"col_1 value", ...}
.Ainsi, la requête ressemblerait à quelque chose comme:
et retournerait des lignes comme:
(Je suis maintenant sur Postgres 9.5.3 et je ne suis pas sûr à 100% quand ce support a été ajouté.)
la source
Vous pouvez utiliser
json_build_object
comme çala source