Yan*_*hon 8 postgresql join postgresql-9.4
像这样的查询
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;
Run Code Online (Sandbox Code Playgroud)
执行时,c和b将彼此相乘并在 JSON 数组对象中产生重复的条目。
我尝试将查询更改为使用 2 个子查询,但出现各种错误和警告,例如“子查询必须只返回一列”等。
我也尝试使用LEFT OUTER JOIN,但我想我还没有掌握连接表的工作原理,因为它仅适用于b并且c仍然相乘并包含重复项。
编辑:DISTINCT在COALESCE函数上使用带有“无法识别 json 类型的相等运算符”的错误。
如何修复此查询并仅聚合唯一行?
我需要指定表b和c实际上都是VIEWs,而且它们都至少有一json_agg列,所以我不能只使用json_agg(DISTINCT b.*). 这太容易了。
这是一个重现问题的小片段:
--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;
Run Code Online (Sandbox Code Playgroud)
退货
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"}}]"
Run Code Online (Sandbox Code Playgroud)
我找到了解决办法。我不确定它是否是最佳的,但它有效。
SELECT tbl_a.id, tbl_a.name,
COALESCE( ( SELECT json_agg(tbl_b.*)
FROM tbl_b
WHERE tbl_b.a_id = tbl_a.id ), '{}'::json),
COALESCE( ( SELECT json_agg(tbl_c.*)
FROM tbl_c
WHERE tbl_c.a_id = tbl_a.id ), '{}'::json)
FROM tbl_a;
Run Code Online (Sandbox Code Playgroud)
哪个正确返回
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":"def"}}]"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4476 次 |
| 最近记录: |