Postgres 9.3 を使用しています。
私は2つのテーブルT1
とそれらの間T2
のn:m
関係を持ってT1_T2_rel
います。ここで、T1 の列に加えて、T1 の各レコードに対して、T2 のすべての関連レコードの主キー ID を持つ配列を含む列を提供するビューを作成したいと思います。T2 に関連するエントリがない場合、この列の対応するフィールドには null 値が含まれます。
私のスキーマの抽象化されたバージョンは次のようになります。
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 は を使用する場合は集計テーブルの順次スキャンに頼りleft join
ますが、 の場合はインデックス スキャンが使用されますleft join lateral
。