Postgres 9.4 lub nowszy
Oczywiście zainspirowany tym postem Postgres 9.4 dodał brakujące funkcje:
Podziękowania dla Laurence'a Rowe za łatkę i Andrew Dunstana za zatwierdzenie!
Aby odczepić tablicę JSON. Następnie użyj array_agg()
lub konstruktora ARRAY, aby zbudować z niego tablicę Postgres . Lub string_agg()
zbudować text
ciąg .
Agreguj niezanieczyszczone elementy na wiersz w LATERAL
podkwerendie lub skorelowanej. Następnie pierwotny porządek jest zachowany i nie musimy ORDER BY
, GROUP BY
a nawet unikalny klucz w zapytaniu zewnętrznym. Widzieć:
Zamień „json” na „jsonb” dla jsonb
wszystkich następujących kodów 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;
Krótka składnia:
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;
Związane z:
Konstruktor ARRAY w skorelowanym podzapytaniu:
SELECT tbl_id, ARRAY(SELECT json_array_elements_text(t.data->'tags')) AS txt_arr
FROM tbl t;
Związane z:
Subtelna różnica : null
elementy są zachowywane w rzeczywistych tablicach . Nie jest to możliwe w powyższych zapytaniach generujących text
ciąg, który nie może zawierać null
wartości. Prawdziwy obraz jest tablicą.
Opakowanie funkcji
W celu wielokrotnego użycia, aby uczynić to jeszcze prostszym, enkapsuluj logikę w funkcji:
CREATE OR REPLACE FUNCTION json_arr2text_arr(_js json)
RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT json_array_elements_text(_js))';
Zrób z tego funkcję SQL , aby można ją było wstawiać w większych zapytaniach.
Zrób to IMMUTABLE
(bo tak jest), aby uniknąć powtarzania oceny w większych zapytaniach i zezwól na to w wyrażeniach indeksowych.
Połączenie:
SELECT tbl_id, json_arr2text_arr(data->'tags')
FROM tbl;
db <> skrzypce tutaj
Postgres 9.3 lub starszy
Użyj funkcji json_array_elements()
. Ale otrzymujemy z niego ciągi cudzysłowów .
Alternatywne zapytanie z agregacją w zapytaniu zewnętrznym. CROSS JOIN
usuwa wiersze z brakującymi lub pustymi tablicami. Może być również przydatny do przetwarzania elementów. Potrzebujemy unikalnego klucza do agregacji:
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;
Konstruktor ARRAY, wciąż z ciągami cytowanymi:
SELECT tbl_id, ARRAY(SELECT json_array_elements(t.data->'tags')) AS quoted_txt_arr
FROM tbl t;
Zauważ, że null
jest konwertowany na wartość tekstową „null”, inaczej niż powyżej. Niepoprawne, ściśle mówiąc i potencjalnie dwuznaczne.
Biedny człowiek nie cytuje 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;
Pobierz pojedynczy wiersz z 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;
Ciągi tworzą skorelowane podzapytanie:
SELECT tbl_id, (SELECT string_agg(trim(value::text, '"'), ', ')
FROM json_array_elements(t.data->'tags')) AS list
FROM tbl t;
Konstruktor ARRAY:
SELECT tbl_id, ARRAY(SELECT trim(value::text, '"')
FROM json_array_elements(t.data->'tags')) AS txt_arr
FROM tbl t;
Oryginalne (nieaktualne) skrzypce SQL .
db <> skrzypce tutaj.
Związane z:
Uwagi (nieaktualne od str. 9.4)
Potrzebowalibyśmy json_array_elements_text(json)
bliźniaka, json_array_elements(json)
aby zwrócić odpowiednie text
wartości z tablicy JSON. Ale wydaje się, że brakuje tego w arsenale funkcji JSON . Lub inna funkcja do wyodrębnienia text
wartości z JSON
wartości skalarnej . Wydaje mi się, że też tego brakuje.
Więc improwizowałem trim()
, ale to się nie powiedzie w nietrywialnych przypadkach ...
json_extract_path_text(your_column, 'tags')
tego szukasz?