我正在使用 Postgres 9.3。
我有两个表T1
和它们之间T2
的n:m
关系T1_T2_rel
。现在我想创建一个视图,除了 T1 的列之外,还提供一个列,对于 T1 中的每条记录,该列包含一个包含 T2 的所有相关记录的主键 ID 的数组。如果 T2 中没有相关条目,则该列的相应字段应包含空值。
我的架构的抽象版本如下所示:
CREATE TABLE T1 ( t1_id serial primary key, t1_data int );
CREATE TABLE T2 ( t2_id serial primary key );
CREATE TABLE T1_T2_rel (
t1_id int references T1( t1_id )
, t2_id int references T2( t2_id )
);
相应的样本数据可以生成如下:
INSERT INTO T1 (t1_data)
SELECT cast(random()*100 as int) FROM generate_series(0,9) c(i);
INSERT INTO T2 (t2_id) SELECT nextval('T2_t2_id_seq') FROM generate_series(0,99);
INSERT INTO T1_T2_rel
SELECT cast(random()*10 as int) % 10 + 1 as t1_id
, cast(random()*99+1 as int) as t2_id
FROM generate_series(0,99);
到目前为止,我提出了以下查询:
SELECT T1.t1_id, T1.t1_data, agg
FROM T1
LEFT JOIN LATERAL (
SELECT t1_id, array_agg(t2_id) as agg
FROM T1_T2_rel
WHERE t1_id=T1.t1_id
GROUP BY t1_id
) as temp ON temp.t1_id=T1.t1_id;
这行得通。但是,可以简化吗?
可以在此处找到相应的小提琴:sql-fiddle。不幸的是,sql-fiddle 不支持横向连接所需的 Postgres 9.3(尚)。
[更新]正如已经指出的那样,left join
原则上简单地使用子查询就足够了。但是,如果我比较查询计划,Postgres 会在使用 a 时对聚合表进行顺序扫描,left join
而在left join lateral
.