TL; DR
SELECT json_agg(t) FROM t
JSON nesneler dizisi için ve
SELECT
json_build_object(
'a', json_agg(t.a),
'b', json_agg(t.b)
)
FROM t
dizilerin JSON nesnesi için.
Nesnelerin listesi
Bu bölümde, her satırın tek bir nesneye dönüştürüldüğü bir JSON nesne dizisinin nasıl oluşturulacağı açıklanmaktadır. Sonuç şuna benzer:
[{"a":1,"b":"value1"},{"a":2,"b":"value2"},{"a":3,"b":"value3"}]
9.3 ve üstü
json_agg
Fonksiyon kutunun dışında bu sonucu üretir. Girdisini JSON'a nasıl dönüştüreceğini otomatik olarak anlar ve bir dizi halinde toplar.
SELECT json_agg(t) FROM t
jsonb
(9.4'te tanıtılan) sürümü yoktur json_agg
. Satırları bir dizi halinde toplayabilir ve sonra dönüştürebilirsiniz:
SELECT to_jsonb(array_agg(t)) FROM t
veya json_agg
bir alçı ile birleştirin :
SELECT json_agg(t)::jsonb FROM t
Benim testlerim onları önce bir dizi halinde birleştirmenin biraz daha hızlı olduğunu gösteriyor. Bunun, dökümün tüm JSON sonucunu ayrıştırması gerektiğinden şüpheleniyorum.
9.2
9.2, json_agg
veya to_json
işlevlerine sahip değildir , bu nedenle eskisini kullanmanız gerekir array_to_json
:
SELECT array_to_json(array_agg(t)) FROM t
İsteğe bağlı row_to_json
olarak sorguya bir arama ekleyebilirsiniz :
SELECT array_to_json(array_agg(row_to_json(t))) FROM t
Bu, her satırı bir JSON nesnesine dönüştürür, JSON nesnelerini bir dizi olarak toplar ve ardından diziyi bir JSON dizisine dönüştürür.
İkisi arasında önemli bir performans farkı fark edemedim.
Listelerin amacı
Bu bölümde, her anahtarın tablodaki bir sütun olduğu ve her bir değerin sütunun değerlerinin bir dizisi olduğu bir JSON nesnesinin nasıl oluşturulacağı açıklanmaktadır. Şuna benzeyen sonuç:
{"a":[1,2,3], "b":["value1","value2","value3"]}
9.5 ve üstü
Şu json_build_object
işlevi kullanabiliriz:
SELECT
json_build_object(
'a', json_agg(t.a),
'b', json_agg(t.b)
)
FROM t
Ayrıca sütunları bir araya getirebilir, tek bir satır oluşturabilir ve ardından bunu bir nesneye dönüştürebilirsiniz:
SELECT to_json(r)
FROM (
SELECT
json_agg(t.a) AS a,
json_agg(t.b) AS b
FROM t
) r
Nesnenin istenen adlara sahip olduğundan emin olmak için dizilerin takma adının kesinlikle gerekli olduğunu unutmayın.
Hangisinin daha net olduğu bir fikir meselesidir. json_build_object
Fonksiyonu kullanıyorsanız, okunabilirliği artırmak için bir satıra bir anahtar / değer çifti koymanızı şiddetle tavsiye ederim.
Ayrıca kullanabilirsiniz array_agg
yerine json_agg
, ancak test gösterir json_agg
biraz daha hızlıdır.
İşlevin bir jsonb
sürümü yok json_build_object
. Tek bir satırda toplayabilir ve şunları dönüştürebilirsiniz:
SELECT to_jsonb(r)
FROM (
SELECT
array_agg(t.a) AS a,
array_agg(t.b) AS b
FROM t
) r
Bu tür sonuçlar için diğer sorguların aksine, array_agg
kullanırken biraz daha hızlı görünmektedir to_jsonb
. Bunun JSON sonucunun ayrıştırılması ve doğrulanmasından kaynaklandığından şüpheleniyorum json_agg
.
Veya açık bir atama kullanabilirsiniz:
SELECT
json_build_object(
'a', json_agg(t.a),
'b', json_agg(t.b)
)::jsonb
FROM t
to_jsonb
Versiyon benim testine göre daha hızlı döküm önlemek için izin verir ve olduğu; Yine, bunun sonucu ayrıştırma ve doğrulama ek yükünden kaynaklandığından şüpheleniyorum.
9.4 ve 9.3
json_build_object
Önceki sürümlerinde bir nesneye agrega ve dönüştürmek zorunda fonksiyonu, 9.5 yeniydi:
SELECT to_json(r)
FROM (
SELECT
json_agg(t.a) AS a,
json_agg(t.b) AS b
FROM t
) r
veya
SELECT to_jsonb(r)
FROM (
SELECT
array_agg(t.a) AS a,
array_agg(t.b) AS b
FROM t
) r
Eğer istemenize bağlı json
veya jsonb
.
(9.3'te yok jsonb
.)
9.2
9.2'de bile to_json
yok. Kullanmalısınız row_to_json
:
SELECT row_to_json(r)
FROM (
SELECT
array_agg(t.a) AS a,
array_agg(t.b) AS b
FROM t
) r
belgeleme
JSON işlevleri için dokümanlara ulaşın JSON fonksiyonları .
json_agg
üzerinde toplama işlevleri sayfa.
tasarlamak
Performans önemliyse, testlerime güvenmek yerine sorgularınızı kendi şemanız ve verilerinizle karşılaştırdığınızdan emin olun.
İyi bir tasarım olup olmadığı, gerçekten uygulamanıza bağlıdır. Sürdürülebilirlik açısından, belirli bir sorun görmüyorum. Uygulama kodunuzu basitleştirir ve uygulamanın bu bölümünde bakım yapılması gereken daha az şey olduğu anlamına gelir. Eğer PG size kutudan çıkardığınız gibi tam olarak ihtiyacınız olan sonucu verebilirse, kullanmamak için aklıma gelen tek sebep performans kaygısı olacaktır. Tekerleği ve hepsini yeniden icat etmeyin.
Boşlara
Toplama işlevleri genellikle NULL
sıfır satırın üzerinde çalıştıklarında geri verir. Bu bir olasılıksa, COALESCE
onlardan kaçınmak için kullanmak isteyebilirsiniz . Birkaç örnek:
SELECT COALESCE(json_agg(t), '[]'::json) FROM t
Veya
SELECT to_jsonb(COALESCE(array_agg(t), ARRAY[]::t[])) FROM t
Bunu işaret ettiği için Hannes Landeholm'a kredi