Postgres 9.4 atau lebih baru
Jelas terinspirasi oleh posting ini , Postgres 9.4 menambahkan fungsi yang hilang:
Terima kasih kepada Laurence Rowe untuk patch dan Andrew Dunstan untuk melakukan!
Untuk membatalkan array JSON. Kemudian gunakan array_agg()
atau konstruktor ARRAY untuk membangun array Postgres darinya. Atau string_agg()
untuk membangun text
string .
Agregasikan elemen yang tidak diuji per baris dalam LATERAL
subquery yang berkorelasi. Kemudian pesanan asli dipertahankan dan kami tidak perlu ORDER BY
, GROUP BY
atau bahkan kunci unik di kueri luar. Lihat:
Ganti 'json' dengan 'jsonb' untuk jsonb
semua kode SQL berikut.
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;
Sintaks pendek:
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;
Terkait:
Konstruktor ARRAY dalam subquery berkorelasi:
SELECT tbl_id, ARRAY(SELECT json_array_elements_text(t.data->'tags')) AS txt_arr
FROM tbl t;
Terkait:
Perbedaan halus : null
elemen dipertahankan dalam array yang sebenarnya . Ini tidak mungkin dalam kueri di atas yang menghasilkan text
string, yang tidak bisa berisi null
nilai. The representasi sejati adalah array.
Fungsi pembungkus
Untuk penggunaan berulang, untuk membuatnya lebih sederhana, merangkum logika dalam suatu fungsi:
CREATE OR REPLACE FUNCTION json_arr2text_arr(_js json)
RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT json_array_elements_text(_js))';
Jadikan sebagai fungsi SQL , sehingga bisa diuraikan dalam kueri yang lebih besar.
Buatlah IMMUTABLE
(karena memang demikian) untuk menghindari evaluasi berulang dalam permintaan yang lebih besar dan memungkinkannya dalam ekspresi indeks.
Panggilan:
SELECT tbl_id, json_arr2text_arr(data->'tags')
FROM tbl;
db <> biola di sini
Postgres 9.3 atau lebih tua
Gunakan fungsinya json_array_elements()
. Tapi kami mendapatkan string yang dikutip ganda .
Kueri alternatif dengan agregasi dalam kueri luar. CROSS JOIN
menghapus baris dengan array yang hilang atau kosong. Semoga bermanfaat untuk memproses elemen. Kami membutuhkan kunci unik untuk agregat:
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, masih dengan string yang dikutip:
SELECT tbl_id, ARRAY(SELECT json_array_elements(t.data->'tags')) AS quoted_txt_arr
FROM tbl t;
Catatan yang null
dikonversi ke nilai teks "null", tidak seperti di atas. Tidak benar, benar-benar berbicara, dan berpotensi ambigu.
Orang miskin tidak mengutip dengan 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;
Ambil satu baris dari 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;
String membentuk subquery yang dikorelasikan:
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;
Biola SQL Asli (kedaluwarsa) .
db <> biola di sini.
Terkait:
Catatan (kedaluwarsa sejak pg 9.4)
Kita akan membutuhkan json_array_elements_text(json)
, kembaran json_array_elements(json)
untuk mengembalikan text
nilai yang tepat dari array JSON. Tapi itu tampaknya hilang dari gudang fungsi JSON yang disediakan . Atau fungsi lain untuk mengekstraksi text
nilai dari JSON
nilai skalar . Sepertinya aku juga kehilangan yang itu.
Jadi saya berimprovisasi dengan trim()
, tetapi itu akan gagal untuk kasus-kasus non-sepele ...
json_extract_path_text(your_column, 'tags')
yang Anda cari?