Postgres 9.4 oder neuer
Postgres 9.4 wurde offensichtlich von diesem Beitrag inspiriert und fügte die fehlenden Funktionen hinzu:
Danke an Laurence Rowe für den Patch und Andrew Dunstan für das Commit!
So entfernen Sie das JSON-Array. Verwenden Sie dann array_agg()
oder einen ARRAY-Konstruktor , um ein Postgres- Array daraus zu erstellen . Oder string_agg()
um einen text
String zu bauen .
Aggregieren Sie nicht verschachtelte Elemente pro Zeile in einer LATERAL
oder einer korrelierten Unterabfrage. Dann wird ursprünglicher Auftrag erhalten und wir nicht brauchen ORDER BY
, GROUP BY
oder sogar ein eindeutiger Schlüssel in der äußeren Abfrage. Sehen:
Ersetzen Sie 'json' jsonb
in allen folgenden SQL-Codes durch 'jsonb' .
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;
Kurze Syntax:
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;
Verbunden:
ARRAY-Konstruktor in korrelierter Unterabfrage:
SELECT tbl_id, ARRAY(SELECT json_array_elements_text(t.data->'tags')) AS txt_arr
FROM tbl t;
Verbunden:
Subtiler Unterschied : null
Elemente bleiben in tatsächlichen Arrays erhalten . Dies ist in den obigen Abfragen, die eine text
Zeichenfolge erzeugen , die keine null
Werte enthalten kann, nicht möglich . Die wahre Darstellung ist ein Array.
Funktions-Wrapper
Um dies noch einfacher zu machen, kapseln Sie bei wiederholter Verwendung die Logik in eine Funktion:
CREATE OR REPLACE FUNCTION json_arr2text_arr(_js json)
RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT json_array_elements_text(_js))';
Machen Sie es zu einer SQL-Funktion , damit es in größeren Abfragen eingebunden werden kann.
Machen Sie es IMMUTABLE
(weil es ist), um wiederholte Auswertung in größeren Abfragen zu vermeiden und es in Indexausdrücken zuzulassen.
Anruf:
SELECT tbl_id, json_arr2text_arr(data->'tags')
FROM tbl;
db <> hier fummeln
Postgres 9.3 oder älter
Nutzen Sie die Funktion json_array_elements()
. Aber wir bekommen doppelte Anführungszeichen .
Alternative Abfrage mit Aggregation in der äußeren Abfrage. CROSS JOIN
Entfernt Zeilen mit fehlenden oder leeren Arrays. Kann auch zur Verarbeitung von Elementen nützlich sein. Wir benötigen einen eindeutigen Schlüssel für die Aggregation:
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;
ARRAY-Konstruktor, immer noch mit zitierten Zeichenfolgen:
SELECT tbl_id, ARRAY(SELECT json_array_elements(t.data->'tags')) AS quoted_txt_arr
FROM tbl t;
Beachten Sie, dass null
im Gegensatz zu oben in den Textwert "null" konvertiert wird. Falsch, genau genommen und möglicherweise mehrdeutig.
Der arme Mann spricht nicht mit 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;
Rufen Sie eine einzelne Zeile von tbl ab:
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;
Zeichenfolgen bilden eine korrelierte Unterabfrage:
SELECT tbl_id, (SELECT string_agg(trim(value::text, '"'), ', ')
FROM json_array_elements(t.data->'tags')) AS list
FROM tbl t;
ARRAY-Konstruktor:
SELECT tbl_id, ARRAY(SELECT trim(value::text, '"')
FROM json_array_elements(t.data->'tags')) AS txt_arr
FROM tbl t;
Ursprüngliche (veraltete) SQL-Geige .
db <> hier fummeln .
Verbunden:
Anmerkungen (veraltet seit Seite 9.4)
Wir benötigen a json_array_elements_text(json)
, den Zwilling von json_array_elements(json)
, um korrekte text
Werte aus einem JSON-Array zurückzugeben. Dies scheint jedoch im bereitgestellten Arsenal von JSON-Funktionen zu fehlen . Oder eine andere Funktion, um einen text
Wert aus einem Skalarwert zu extrahieren JSON
. Das scheint mir auch zu fehlen.
Also habe ich mit improvisiert trim()
, aber das wird für nicht-triviale Fälle scheitern ...
json_extract_path_text(your_column, 'tags')
was du suchst