Postgres 9.4 veya daha yeni
Açıkçası bu yazıdan ilham alan Postgres 9.4, eksik işlevleri ekledi:
Yama için Laurence Rowe ve kararlılık için Andrew Dunstan'a teşekkürler!
JSON dizisini yanlışlamak için. Sonra ondan bir Postgres dizisi oluşturmak için array_agg()
veya bir ARRAY yapıcısı kullanın . Veya bir dize oluşturmak için .string_agg()
text
LATERAL
Veya bir ilişkili alt sorguda satır başına toplanamayan öğeleri . Ardından orijinal sipariş korunur ve ihtiyacımız yoktur ORDER BY
, GROUP BY
hatta dış sorguda benzersiz bir anahtara da. Görmek:
'Json' ifadesini jsonb
aşağıdaki tüm SQL kodlarında 'jsonb' ile değiştirin .
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;
Kısa sözdizimi:
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;
İlgili:
İlişkili alt sorgudaki ARRAY yapıcısı:
SELECT tbl_id, ARRAY(SELECT json_array_elements_text(t.data->'tags')) AS txt_arr
FROM tbl t;
İlgili:
İnce fark : null
Elementler gerçek dizilerde korunur . Bu, değerleri text
içermeyen bir dize üreten yukarıdaki sorgularda mümkün değildir null
. Gerçek gösterimi bir dizidir.
İşlev sargısı
Tekrarlanan kullanımda, bunu daha da kolaylaştırmak için, mantığı bir fonksiyonla kaplayın:
CREATE OR REPLACE FUNCTION json_arr2text_arr(_js json)
RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT json_array_elements_text(_js))';
Bunu bir SQL işlevi yapın , böylece daha büyük sorgularda sıraya alınabilir .
Daha IMMUTABLE
büyük sorgularda tekrarlanan değerlendirmeyi önlemek ve dizin ifadelerinde izin vermek için (çünkü) yapın.
Aramak:
SELECT tbl_id, json_arr2text_arr(data->'tags')
FROM tbl;
db <> burada keman
Postgres 9.3 veya daha büyük
İşlevi kullanın json_array_elements()
. Ama ondan çift alıntılı dizge alıyoruz .
Dış sorguda toplama ile alternatif sorgu. CROSS JOIN
eksik veya boş dizileri olan satırları kaldırır. Öğeleri işlemek için de yararlı olabilir. Toplanacak benzersiz bir anahtara ihtiyacımız var:
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 yapıcısı, hala alıntılanmış dizelerle:
SELECT tbl_id, ARRAY(SELECT json_array_elements(t.data->'tags')) AS quoted_txt_arr
FROM tbl t;
null
Yukarıdakilerin aksine, "null" metin değerine dönüştürüldüğünü not edin . Yanlış, kesinlikle konuşma ve belirsiz.
Zavallı adam şununla alıntı yapmıyor 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;
Tek bir satırı tbl'den al:
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;
Dizeler ilişkili alt sorgu oluşturur:
SELECT tbl_id, (SELECT string_agg(trim(value::text, '"'), ', ')
FROM json_array_elements(t.data->'tags')) AS list
FROM tbl t;
ARRAY yapıcı:
SELECT tbl_id, ARRAY(SELECT trim(value::text, '"')
FROM json_array_elements(t.data->'tags')) AS txt_arr
FROM tbl t;
Orijinal (eski) SQL Fiddle .
db <> burada keman .
İlgili:
Notlar (pg 9.4'ten beri eski)
Bir JSON dizisinden uygun değerleri döndürmek için bir json_array_elements_text(json)
, ikizi gerekir . Ancak bu JSON işlevlerinin sağladığı cephanelikten eksik gibi görünüyor . Veya skaler bir değerden bir değer çıkarmak için başka bir fonksiyon . Ben de onu özlüyorum.
Bu yüzden doğaçlama yaptım , ama bu önemsiz olmayan durumlar için başarısız olacak ...json_array_elements(json)
text
text
JSON
trim()
json_extract_path_text(your_column, 'tags')
şey mi?