Với một truy vấn như thế này
SELECT a.id, a.name,
COALESCE( json_agg(b.*), '[]'::json ),
COALESCE( json_agg(c.*), '[]'::json ),
FROM a
LEFT JOIN b ON a.id = b.a_id
LEFT JOIN c ON a.id = c.a_id
GROUP BY a.id, a.name;
Khi được thực thi, cả hai c
và b
sẽ được nhân với nhau và tạo ra các mục trùng lặp trong đối tượng mảng JSON.
Tôi đã thử thay đổi truy vấn để sử dụng 2 truy vấn con thay thế, nhưng tôi nhận được tất cả các loại lỗi và cảnh báo, chẳng hạn như "Truy vấn con chỉ phải trả về một cột", v.v.
Tôi cũng đã thử sử dụng LEFT OUTER JOIN
, nhưng tôi đoán tôi chưa nắm vững cách thức các bảng tham gia hoạt động vì nó chỉ áp dụng cho b
và c
vẫn được nhân lên và chứa các bản sao.
Chỉnh sửa : sử dụng các DISTINCT
lỗi với "không thể xác định toán tử đẳng thức cho kiểu json" trên các COALESCE
hàm.
Làm cách nào tôi có thể sửa truy vấn này và chỉ tổng hợp các hàng duy nhất?
Chỉnh sửa 2
Tôi cần xác định rằng cả hai bảng b
và c
thực sự VIEW
là s và cả hai đều có ít nhất một json_agg
cột, vì vậy tôi không thể chỉ sử dụng json_agg(DISTINCT b.*)
. Điều này đã trở nên quá dễ dàng.
Chỉnh sửa 3
Đây là một đoạn nhỏ để tái tạo vấn đề:
--DROP TABLE IF EXISTS tbl_a CASCADE;
--DROP TABLE IF EXISTS tbl_b CASCADE;
--DROP TABLE IF EXISTS tbl_c CASCADE;
CREATE TABLE tbl_a (
id bigserial NOT NULL,
name character varying(16),
CONSTRAINT "PK_tbl_a" PRIMARY KEY (id)
) WITH ( OIDS=FALSE );
CREATE TABLE tbl_b (
a_id bigint NOT NULL,
foo json NOT NULL DEFAULT '{}'::json,
CONSTRAINT "FK_tbl_b_a" FOREIGN KEY (a_id)
REFERENCES tbl_a (id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
) WITH ( OIDS=FALSE );
CREATE TABLE tbl_c (
a_id bigint NOT NULL,
bar json NOT NULL DEFAULT '{}'::json,
CONSTRAINT "FK_tbl_c_a" FOREIGN KEY (a_id)
REFERENCES tbl_a (id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
) WITH ( OIDS=FALSE );
INSERT INTO tbl_a (id,name) VALUES (1, 'Test');
INSERT INTO tbl_b (a_id, foo) VALUES (1, '{"foo":"Hello"}'::json), (1, '{"foo":"World"}'::json);
INSERT INTO tbl_c (a_id, bar) VALUES (1, '{"bar":"abc"}'::json), (1, '{"bar":"def"}'::json);
SELECT tbl_a.id, tbl_a.name,
COALESCE(json_agg(tbl_b.*), '{}'::json),
COALESCE(json_agg(tbl_c.*), '{}'::json)
FROM tbl_a
LEFT JOIN tbl_b ON tbl_a.id = tbl_b.a_id
LEFT JOIN tbl_c ON tbl_a.id = tbl_c.a_id
GROUP BY tbl_a.id, tbl_a.name;
Trả về
id name coalesce coalesce
-- ------ ------------------------------------ ----------------------
1 "Test" "[{"a_id":1,"foo":{"foo":"World"}}, "[{"a_id":1,"bar":{"bar":"abc"}},
{"a_id":1,"foo":{"foo":"Hello"}}, {"a_id":1,"bar":{"bar":"abc"}},
{"a_id":1,"foo":{"foo":"World"}}, {"a_id":1,"bar":{"bar":"def"}},
{"a_id":1,"foo":{"foo":"Hello"}}]" {"a_id":1,"bar":{"bar":"def"}}]"