これは機能します:
SELECT *
FROM element
WHERE (pk1, pk2, pk3) IN (SELECT (unnest(elements)).*
FROM collection
WHERE id = 1);
または、より冗長ですが、望ましい :
SELECT *
FROM element
WHERE (pk1, pk2, pk3) IN (SELECT (e).*
FROM collection c, unnest(c.elements) e
WHERE c.id = 1);
より堅牢になり、unnest()
の評価を回避します 複数回。参照:
これも機能します:
SELECT *
FROM element
WHERE ROW((pk1, pk2, pk3)) IN (SELECT unnest(elements)
FROM collection
WHERE id = 1);
問題の核心は、 IN
サブクエリを取得する 2つの別々の形式を知っています。 マニュアルの引用:
失敗したクエリ あなたが(当然のことながら)最初の形式を期待している間に、2番目の形式に解決されます。しかし、2番目の形式はこれを行います:
私の最初と2番目のクエリ 行タイプを分解する
ことで機能させる オペレーターの右側。したがって、Postgresには3つのbigint
があります 左右の値で満足しています。
私の3番目のクエリ 行タイプを別の
キーワードROW
に注意してください ラップする単一のフィールドに必要です。 マニュアル:
作業中のクエリ リストを提供するため、微妙に異なります サブクエリの代わりに右側の値の (セット )。これは、異なるコードパスを使用する異なる実装です。マニュアルの
= ANY
を使用した、より同等の(機能する)構文バリアント :
SELECT * FROM element
WHERE (pk1, pk2, pk3) = ANY ('{"(1,2,3)","(2,3,4)"}'::element_pk_t[]);
SELECT * FROM element
WHERE (pk1, pk2, pk3) = ANY (ARRAY[(1,2,3)::element_pk_t,(2,3,4)::element_pk_t]);
SELECT * FROM element
WHERE (pk1, pk2, pk3) = ANY (ARRAY[(1,2,3),(2,3,4)]::element[]);
(pk1, pk2, pk3)::element_pk_t
でも有効です またはROW(pk1, pk2, pk3)::element_pk_t
参照:
ソースは配列なので 、(e.pk1, e.pk2, e.pk3) = ANY(c.elements)
を使用したDanielの2番目のクエリ 自然に役立ちます。
しかし、最速のクエリに賭けるには 、PKインデックスを最適に使用することを期待しているため、私のお金は2番目のバリアントにあります。
概念実証と同じように。 a_horseがコメントしたように、正規化されたDB設計はおそらく最適に拡張できます。