Thật không may, cú pháp SQL không có quy định nào để nói "tất cả các cột ngoại trừ một cột này" . Bạn có thể đạt được mục tiêu của mình bằng cách đánh vần danh sách các cột còn lại trong biểu thức loại hàng :
SELECT a.id, a.name
, json_agg((b.col1, b.col2, b.col3)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
Đó là viết tắt của hình thức rõ ràng hơn : . ROW
(b.col1, b.col2, b.col3)
Tuy nhiên, tên cột không được bảo tồn trong các biểu thức kiểu hàng. Bạn nhận được các tên khóa chung trong đối tượng JSON theo cách này. Tôi thấy 3 tùy chọn để giữ nguyên tên cột ban đầu:
1. Chuyển sang loại đã đăng ký
Truyền đến một loại hàng nổi tiếng (đã đăng ký). Một loại được đăng ký cho mỗi bảng hoặc dạng xem hiện có hoặc với một CREATE TYPE
tuyên bố rõ ràng . Bạn có thể sử dụng bảng tạm thời cho giải pháp đặc biệt (tồn tại trong suốt thời gian của phiên):
CREATE TEMP TABLE x (col1 int, col2 text, col3 date); -- use adequate data types!
SELECT a.id, a.name
, json_agg((b.col1, b.col2, b.col3)::x) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
2. Sử dụng một mục phụ
Sử dụng một subselect để xây dựng một bảng dẫn xuất và tham chiếu toàn bộ bảng . Điều này cũng mang tên cột. Nó dài dòng hơn, nhưng bạn không cần loại đã đăng ký:
SELECT a.id, a.name
, json_agg((SELECT x FROM (SELECT b.col1, b.col2, b.col3) AS x)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
SELECT a.id, a.name
, json_agg(json_build_object('col1', b.col1, 'col2', b.col2, 'col3', b.col3)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
Liên quan:
Tương tự jsonb
với các chức năng tương ứng jsonb_agg()
và jsonb_build_object()
.
Đối với Postgres 9,5 hay muộn cũng thấy câu trả lời a_horse của với một biến thể cú pháp ngắn mới: Postgres thêm toán tử trừ -
chojsonb
nói "tất cả các phím trừ một phím này" .
Vì Postgres 10 "ngoại trừ một số khóa" được triển khai với cùng một toán tử lấy text[]
toán hạng 2 - giống như mlt đã nhận xét.