Postgres 9.4 o successivo
Ovviamente ispirato a questo post , Postgres 9.4 ha aggiunto le funzioni mancanti:
Grazie a Laurence Rowe per la patch e Andrew Dunstan per l'impegno!
Per rovesciare l'array JSON. Quindi utilizzare array_agg()
o un costruttore ARRAY per costruire un array Postgres da esso. O string_agg()
per costruire una text
stringa .
Aggrega elementi non desiderati per riga in una LATERAL
o sottoquery correlata. Quindi l' ordine originale viene preservato e non è necessario ORDER BY
, GROUP BY
o anche una chiave univoca nella query esterna. Vedere:
Sostituisci "json" con "jsonb" per jsonb
in tutto il seguente codice SQL.
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;
Sintassi breve:
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;
Relazionato:
Costruttore ARRAY in subquery correlata:
SELECT tbl_id, ARRAY(SELECT json_array_elements_text(t.data->'tags')) AS txt_arr
FROM tbl t;
Relazionato:
Differenza sottile : gli null
elementi sono conservati in array reali . Questo non è possibile nelle query sopra che producono una text
stringa, che non può contenere null
valori. La vera rappresentazione è un array.
Funzione wrapper
Per un uso ripetuto, per rendere questo ancora più semplice, incapsulare la logica in una funzione:
CREATE OR REPLACE FUNCTION json_arr2text_arr(_js json)
RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT json_array_elements_text(_js))';
Renderlo una funzione SQL , quindi può essere integrato in query più grandi.
Renderlo IMMUTABLE
(perché lo è) per evitare ripetute valutazioni in query più grandi e consentirlo nelle espressioni di indice.
Chiamata:
SELECT tbl_id, json_arr2text_arr(data->'tags')
FROM tbl;
db <> violino qui
Postgres 9.3 o precedente
Utilizzare la funzione json_array_elements()
. Ma otteniamo stringhe tra virgolette doppie da esso.
Query alternativa con aggregazione nella query esterna. CROSS JOIN
rimuove le righe con array mancanti o vuoti. Può essere utile anche per l'elaborazione di elementi. Abbiamo bisogno di una chiave univoca per aggregare:
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;
Costruttore ARRAY, ancora con stringhe tra virgolette:
SELECT tbl_id, ARRAY(SELECT json_array_elements(t.data->'tags')) AS quoted_txt_arr
FROM tbl t;
Si noti che null
viene convertito nel valore di testo "null", diversamente da quanto sopra. Inesatto, a rigor di termini e potenzialmente ambiguo.
Povero uomo che non sta citando 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;
Recupera una singola riga da 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;
Sottoquery correlata forma stringhe:
SELECT tbl_id, (SELECT string_agg(trim(value::text, '"'), ', ')
FROM json_array_elements(t.data->'tags')) AS list
FROM tbl t;
Costruttore ARRAY:
SELECT tbl_id, ARRAY(SELECT trim(value::text, '"')
FROM json_array_elements(t.data->'tags')) AS txt_arr
FROM tbl t;
Fiddle SQL originale (obsoleto) .
db <> violino qui.
Relazionato:
Note (obsolete da pag 9.4)
Avremmo bisogno di un json_array_elements_text(json)
, il gemello di json_array_elements(json)
per restituire i text
valori corretti da un array JSON. Ma questo sembra mancare dall'arsenale fornito di funzioni JSON . O qualche altra funzione per estrarre un text
valore da un JSON
valore scalare . Mi sembra che manchi anche quello.
Così ho improvvisato con trim()
, ma ciò fallirà per casi non banali ...
json_extract_path_text(your_column, 'tags')
quello che stai cercando?