PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Kết quả trả về PostgreSQL được đặt dưới dạng mảng JSON?

TL; DR

SELECT json_agg(t) FROM t

cho một mảng đối tượng JSON và

SELECT
    json_build_object(
        'a', json_agg(t.a),
        'b', json_agg(t.b)
    )
FROM t

cho một đối tượng JSON của mảng.

Danh sách các đối tượng

Phần này mô tả cách tạo một mảng đối tượng JSON, với mỗi hàng được chuyển đổi thành một đối tượng duy nhất. Kết quả như sau:

[{"a":1,"b":"value1"},{"a":2,"b":"value2"},{"a":3,"b":"value3"}]

9.3 trở lên

json_agg hàm tạo ra kết quả này. Nó tự động tìm ra cách chuyển đổi đầu vào của nó thành JSON và tổng hợp nó thành một mảng.

SELECT json_agg(t) FROM t

Không có jsonb (được giới thiệu trong 9.4) phiên bản của json_agg . Bạn có thể tổng hợp các hàng thành một mảng và sau đó chuyển đổi chúng:

SELECT to_jsonb(array_agg(t)) FROM t

hoặc kết hợp json_agg với dàn diễn viên:

SELECT json_agg(t)::jsonb FROM t

Thử nghiệm của tôi cho thấy rằng việc tổng hợp chúng thành một mảng trước tiên sẽ nhanh hơn một chút. Tôi nghi ngờ rằng điều này là do diễn viên phải phân tích cú pháp toàn bộ kết quả JSON.

9.2

9.2 không có json_agg hoặc to_json , vì vậy bạn cần sử dụng array_to_json cũ hơn :

SELECT array_to_json(array_agg(t)) FROM t

Bạn có thể tùy chọn bao gồm một row_to_json gọi trong truy vấn:

SELECT array_to_json(array_agg(row_to_json(t))) FROM t

Điều này sẽ chuyển đổi từng hàng thành một đối tượng JSON, tổng hợp các đối tượng JSON thành một mảng và sau đó chuyển đổi mảng thành một mảng JSON.

Tôi không thể phân biệt được bất kỳ sự khác biệt đáng kể nào về hiệu suất giữa cả hai.

Đối tượng của danh sách

Phần này mô tả cách tạo một đối tượng JSON, với mỗi khóa là một cột trong bảng và mỗi giá trị là một mảng các giá trị của cột. Kết quả giống như sau:

{"a":[1,2,3], "b":["value1","value2","value3"]}

9.5 trở lên

Chúng tôi có thể tận dụng json_build_object chức năng:

SELECT
    json_build_object(
        'a', json_agg(t.a),
        'b', json_agg(t.b)
    )
FROM t

Bạn cũng có thể tổng hợp các cột, tạo một hàng, sau đó chuyển đổi hàng đó thành một đối tượng:

SELECT to_json(r)
FROM (
    SELECT
        json_agg(t.a) AS a,
        json_agg(t.b) AS b
    FROM t
) r

Lưu ý rằng việc đặt răng cưa cho các mảng là hoàn toàn cần thiết để đảm bảo rằng đối tượng có các tên mong muốn.

Cái nào rõ ràng hơn là một vấn đề của ý kiến. Nếu sử dụng json_build_object , tôi thực sự khuyên bạn nên đặt một cặp khóa / giá trị trên một dòng để cải thiện khả năng đọc.

Bạn cũng có thể sử dụng array_agg thay cho json_agg , nhưng thử nghiệm của tôi chỉ ra rằng json_agg nhanh hơn một chút.

Không có jsonb phiên bản của json_build_object hàm số. Bạn có thể tổng hợp thành một hàng và chuyển đổi:

SELECT to_jsonb(r)
FROM (
    SELECT
        array_agg(t.a) AS a,
        array_agg(t.b) AS b
    FROM t
) r

Không giống như các truy vấn khác cho loại kết quả này, array_agg có vẻ nhanh hơn một chút khi sử dụng to_jsonb . Tôi nghi ngờ điều này là do phân tích cú pháp chi phí và xác thực kết quả JSON của json_agg .

Hoặc bạn có thể sử dụng một dàn diễn viên rõ ràng:

SELECT
    json_build_object(
        'a', json_agg(t.a),
        'b', json_agg(t.b)
    )::jsonb
FROM t

to_jsonb phiên bản cho phép bạn tránh diễn viên và nhanh hơn, theo thử nghiệm của tôi; một lần nữa, tôi nghi ngờ điều này là do chi phí phân tích cú pháp và xác thực kết quả.

9,4 và 9,3

json_build_object hàm mới lên 9.5, vì vậy bạn phải tổng hợp và chuyển đổi thành một đối tượng trong các phiên bản trước:

SELECT to_json(r)
FROM (
    SELECT
        json_agg(t.a) AS a,
        json_agg(t.b) AS b
    FROM t
) r

hoặc

SELECT to_jsonb(r)
FROM (
    SELECT
        array_agg(t.a) AS a,
        array_agg(t.b) AS b
    FROM t
) r

tùy thuộc vào việc bạn muốn json hoặc jsonb .

(9.3 không có jsonb .)

9.2

Trong 9.2, thậm chí không phải to_json tồn tại. Bạn phải sử dụng 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

Tài liệu

Tìm tài liệu cho các hàm JSON trong các hàm JSON.

json_agg nằm trên trang chức năng tổng hợp.

Thiết kế

Nếu hiệu suất là quan trọng, hãy đảm bảo bạn đánh giá chuẩn các truy vấn của mình dựa trên lược đồ và dữ liệu của riêng bạn, thay vì tin tưởng vào thử nghiệm của tôi.

Đó là một thiết kế tốt hay không thực sự phụ thuộc vào ứng dụng cụ thể của bạn. Về khả năng bảo trì, tôi không thấy bất kỳ vấn đề cụ thể nào. Nó đơn giản hóa mã ứng dụng của bạn và có nghĩa là có ít thứ phải duy trì hơn trong phần đó của ứng dụng. Nếu PG có thể cung cấp cho bạn chính xác kết quả bạn cần, lý do duy nhất tôi có thể nghĩ đến để không sử dụng nó là cân nhắc về hiệu suất. Đừng phát minh lại bánh xe và tất cả.

Nulls

Các hàm tổng hợp thường trả về NULL khi chúng hoạt động trên không hàng. Nếu đây là khả năng, bạn có thể muốn sử dụng COALESCE để tránh chúng. Một vài ví dụ:

SELECT COALESCE(json_agg(t), '[]'::json) FROM t

Hoặc

SELECT to_jsonb(COALESCE(array_agg(t), ARRAY[]::t[])) FROM t

Tín dụng cho Hannes Landeholm vì đã chỉ ra điều này



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hiển thị hình ảnh từ cơ sở dữ liệu PostgreSQL, bytea

  2. Mối quan hệ không tồn tại

  3. Cách cập nhật nhiều cột trong PostgreSQL

  4. Cách chuyển đổi trường hợp chuỗi trong PostgreSQL

  5. Tại sao tôi không thể sử dụng bí danh cột trong biểu thức SELECT tiếp theo?