TL; DR
SELECT json_agg(t) FROM t
สำหรับอาร์เรย์ของวัตถุ JSON และ
SELECT
json_build_object(
'a', json_agg(t.a),
'b', json_agg(t.b)
)
FROM t
สำหรับออบเจ็กต์ JSON ของอาร์เรย์
รายชื่อวัตถุ
ส่วนนี้อธิบายถึงวิธีการสร้างอาร์เรย์ JSON ของออบเจ็กต์โดยแต่ละแถวจะถูกแปลงเป็นออบเจ็กต์เดียว ผลลัพธ์มีลักษณะดังนี้:
[{"a":1,"b":"value1"},{"a":2,"b":"value2"},{"a":3,"b":"value3"}]
9.3 ขึ้นไป
json_agg
ฟังก์ชั่นการผลิตผลนี้ออกมาจากกล่อง โดยอัตโนมัติจะหาวิธีแปลงอินพุตเป็น JSON และรวมเข้าเป็นอาร์เรย์
SELECT json_agg(t) FROM t
ไม่มีjsonb
(แนะนำในเวอร์ชัน 9.4) ของjson_agg
. คุณสามารถรวมแถวเป็นอาร์เรย์แล้วแปลงได้:
SELECT to_jsonb(array_agg(t)) FROM t
หรือรวมjson_agg
กับนักแสดง:
SELECT json_agg(t)::jsonb FROM t
การทดสอบของฉันชี้ให้เห็นว่าการรวมเข้าในอาร์เรย์ก่อนนั้นเร็วกว่าเล็กน้อย ฉันสงสัยว่านี่เป็นเพราะนักแสดงต้องแยกวิเคราะห์ผลลัพธ์ JSON ทั้งหมด
9.2
9.2 ไม่มีjson_agg
หรือto_json
ฟังก์ชันดังนั้นคุณต้องใช้รุ่นเก่ากว่าarray_to_json
:
SELECT array_to_json(array_agg(t)) FROM t
คุณสามารถเลือกที่จะรวมการrow_to_json
โทรในแบบสอบถาม:
SELECT array_to_json(array_agg(row_to_json(t))) FROM t
สิ่งนี้จะแปลงแต่ละแถวเป็นออบเจ็กต์ JSON รวมออบเจ็กต์ JSON เป็นอาร์เรย์จากนั้นแปลงอาร์เรย์เป็นอาร์เรย์ JSON
ฉันไม่สามารถแยกแยะความแตกต่างของประสิทธิภาพที่สำคัญระหว่างทั้งสองอย่างได้
วัตถุของรายการ
ส่วนนี้อธิบายวิธีการสร้างออบเจ็กต์ JSON โดยแต่ละคีย์เป็นคอลัมน์ในตารางและแต่ละค่าเป็นอาร์เรย์ของค่าของคอลัมน์ ผลลัพธ์จะเป็นดังนี้:
{"a":[1,2,3], "b":["value1","value2","value3"]}
9.5 ขึ้นไป
เราสามารถใช้ประโยชน์จากjson_build_object
ฟังก์ชัน:
SELECT
json_build_object(
'a', json_agg(t.a),
'b', json_agg(t.b)
)
FROM t
คุณยังสามารถรวมคอลัมน์สร้างแถวเดียวจากนั้นแปลงเป็นวัตถุ:
SELECT to_json(r)
FROM (
SELECT
json_agg(t.a) AS a,
json_agg(t.b) AS b
FROM t
) r
โปรดทราบว่าการกำหนดนามแฝงอาร์เรย์เป็นสิ่งจำเป็นอย่างยิ่งเพื่อให้แน่ใจว่าออบเจ็กต์มีชื่อที่ต้องการ
อันไหนชัดเจนกว่าก็เป็นเรื่องของความเห็น หากใช้json_build_object
ฟังก์ชันนี้ขอแนะนำให้วางคู่คีย์ / ค่าหนึ่งคู่ในบรรทัดเพื่อปรับปรุงความสามารถในการอ่าน
คุณยังสามารถใช้array_agg
แทนได้json_agg
แต่การทดสอบของฉันระบุว่าjson_agg
เร็วกว่าเล็กน้อย
ไม่มีjsonb
เวอร์ชันของjson_build_object
ฟังก์ชัน คุณสามารถรวมเป็นแถวเดียวและแปลง:
SELECT to_jsonb(r)
FROM (
SELECT
array_agg(t.a) AS a,
array_agg(t.b) AS b
FROM t
) r
ซึ่งแตกต่างจากการค้นหาอื่น ๆ สำหรับชนิดของผลนี้array_agg
ดูเหมือนว่าจะมีเล็ก ๆ น้อย ๆ to_jsonb
ได้เร็วขึ้นเมื่อใช้ ฉันสงสัยว่านี่เป็นเพราะการแยกวิเคราะห์ค่าใช้จ่ายและการตรวจสอบผลลัพธ์ JSON ของjson_agg
.
หรือคุณสามารถใช้นักแสดงที่ชัดเจน:
SELECT
json_build_object(
'a', json_agg(t.a),
'b', json_agg(t.b)
)::jsonb
FROM t
to_jsonb
รุ่นช่วยให้คุณหลีกเลี่ยงการหล่อและเป็นเร็วขึ้นตามการทดสอบของฉัน; อีกครั้งฉันสงสัยว่านี่เป็นเพราะค่าใช้จ่ายในการแยกวิเคราะห์และตรวจสอบผลลัพธ์
9.4 และ 9.3
json_build_object
ฟังก์ชั่นใหม่ 9.5 เพื่อให้คุณมีการรวมและการแปลงไปยังวัตถุในรุ่นก่อนหน้านี้:
SELECT to_json(r)
FROM (
SELECT
json_agg(t.a) AS a,
json_agg(t.b) AS b
FROM t
) r
หรือ
SELECT to_jsonb(r)
FROM (
SELECT
array_agg(t.a) AS a,
array_agg(t.b) AS b
FROM t
) r
ขึ้นอยู่กับว่าคุณต้องการหรือjson
jsonb
(9.3 ไม่มีjsonb
)
9.2
ใน 9.2 ไม่มีto_json
อยู่ด้วยซ้ำ คุณต้องใช้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
เอกสาร
ค้นหาเอกสารสำหรับฟังก์ชั่น JSON ในฟังก์ชั่น JSON
json_agg
อยู่ในหน้าฟังก์ชันการรวม
ออกแบบ
หากประสิทธิภาพเป็นสิ่งสำคัญตรวจสอบให้แน่ใจว่าคุณเปรียบเทียบการสืบค้นของคุณกับสคีมาและข้อมูลของคุณเองแทนที่จะเชื่อการทดสอบของฉัน
ไม่ว่าจะเป็นการออกแบบที่ดีหรือไม่ขึ้นอยู่กับแอปพลิเคชันเฉพาะของคุณ ในแง่ของการบำรุงรักษาฉันไม่เห็นปัญหาใด ๆ ช่วยลดความซับซ้อนของรหัสแอปของคุณและหมายความว่ามีการดูแลรักษาน้อยกว่าในส่วนนั้นของแอป หาก PG สามารถให้ผลลัพธ์ที่คุณต้องการได้อย่างตรงจุดเหตุผลเดียวที่ฉันคิดว่าจะไม่ใช้ก็คือการพิจารณาประสิทธิภาพ อย่าสร้างล้อใหม่และทั้งหมด
nulls
โดยทั่วไปฟังก์ชันรวมจะคืนค่าNULL
เมื่อทำงานเกินแถวศูนย์ หากเป็นไปได้คุณอาจต้องใช้COALESCE
เพื่อหลีกเลี่ยง ตัวอย่างสองสามตัวอย่าง:
SELECT COALESCE(json_agg(t), '[]'::json) FROM t
หรือ
SELECT to_jsonb(COALESCE(array_agg(t), ARRAY[]::t[])) FROM t
ให้เครดิตHannes Landeholm ที่ชี้ให้เห็นสิ่งนี้