Postgres 9.4 ou plus récent
Visiblement inspiré par ce billet , Postgres 9.4 a ajouté la (les) fonction (s) manquante (s):
Merci à Laurence Rowe pour le correctif et Andrew Dunstan pour son engagement!
Pour annuler le tableau JSON. Ensuite, utilisez array_agg()
ou un constructeur ARRAY pour construire un tableau Postgres à partir de celui-ci. Ou string_agg()
pour construire une text
chaîne .
Agrégez les éléments non imbriqués par ligne dans une LATERAL
sous-requête ou une sous-requête corrélée. Ensuite, l'ordre d'origine est conservé et nous n'avons pas besoin ORDER BY
, GROUP BY
ni même d'une clé unique dans la requête externe. Voir:
Remplacez "json" par "jsonb" jsonb
dans tout le code SQL suivant.
SELECT t.tbl_id, d.list
FROM tbl t
CROSS JOIN LATERAL (
SELECT string_agg(d.elem::text, ', ') AS list
FROM json_array_elements_text(t.data->'tags') AS d(elem)
) d;
Syntaxe courte:
SELECT t.tbl_id, d.list
FROM tbl t, LATERAL (
SELECT string_agg(value::text, ', ') AS list
FROM json_array_elements_text(t.data->'tags') -- col name default: "value"
) d;
Apparenté, relié, connexe:
Constructeur ARRAY dans une sous-requête corrélée:
SELECT tbl_id, ARRAY(SELECT json_array_elements_text(t.data->'tags')) AS txt_arr
FROM tbl t;
Apparenté, relié, connexe:
Différence subtile : les null
éléments sont conservés dans des tableaux réels . Ceci n'est pas possible dans les requêtes ci-dessus produisant une text
chaîne, qui ne peut pas contenir de null
valeurs. La vraie représentation est un tableau.
Fonction wrapper
Pour une utilisation répétée, pour simplifier encore plus, encapsulez la logique dans une fonction:
CREATE OR REPLACE FUNCTION json_arr2text_arr(_js json)
RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT json_array_elements_text(_js))';
Faites-en une fonction SQL , afin qu'il puisse être intégré dans des requêtes plus volumineuses.
Faites-le IMMUTABLE
(parce que c'est le cas) pour éviter les évaluations répétées dans les requêtes plus volumineuses et autorisez-le dans les expressions d'index.
Appel:
SELECT tbl_id, json_arr2text_arr(data->'tags')
FROM tbl;
db <> fiddle ici
Postgres 9.3 ou plus ancien
Utilisez la fonction json_array_elements()
. Mais nous en tirons une double chaîne .
Requête alternative avec agrégation dans la requête externe. CROSS JOIN
supprime les lignes avec des tableaux manquants ou vides. Peut aussi être utile pour traiter des éléments. Nous avons besoin d'une clé unique pour agréger:
SELECT t.tbl_id, string_agg(d.elem::text, ', ') AS list
FROM tbl t
CROSS JOIN LATERAL json_array_elements(t.data->'tags') AS d(elem)
GROUP BY t.tbl_id;
Le constructeur ARRAY, toujours avec les chaînes citées:
SELECT tbl_id, ARRAY(SELECT json_array_elements(t.data->'tags')) AS quoted_txt_arr
FROM tbl t;
Notez que cela null
est converti en la valeur de texte "null", contrairement à ci-dessus. Incorrect, à proprement parler, et potentiellement ambigu.
Le pauvre homme sans scrupule avec trim()
:
SELECT t.tbl_id, string_agg(trim(d.elem::text, '"'), ', ') AS list
FROM tbl t, json_array_elements(t.data->'tags') d(elem)
GROUP BY 1;
Récupérer une seule ligne de tbl:
SELECT string_agg(trim(d.elem::text, '"'), ', ') AS list
FROM tbl t, json_array_elements(t.data->'tags') d(elem)
WHERE t.tbl_id = 1;
Les chaînes forment une sous-requête corrélée:
SELECT tbl_id, (SELECT string_agg(trim(value::text, '"'), ', ')
FROM json_array_elements(t.data->'tags')) AS list
FROM tbl t;
ARRAY constructeur:
SELECT tbl_id, ARRAY(SELECT trim(value::text, '"')
FROM json_array_elements(t.data->'tags')) AS txt_arr
FROM tbl t;
Fiddle SQL original (obsolète) .
db <> fiddle ici.
Apparenté, relié, connexe:
Notes (obsolète depuis la page 9.4)
Nous aurions besoin de json_array_elements_text(json)
, le jumeau de json_array_elements(json)
pour renvoyer les text
valeurs appropriées d'un tableau JSON. Mais cela semble manquer à l' arsenal fourni de fonctions JSON . Ou une autre fonction pour extraire une text
valeur d'une JSON
valeur scalaire . Il me semble qu'il me manque aussi celui-là.
J'ai donc improvisé avec trim()
, mais cela échouera pour des cas non triviaux ...
json_extract_path_text(your_column, 'tags')
ce que vous cherchez?