はい、重複演算子&&
配列にGINインデックスを使用できます
。特定の人物の行を検索するためにこれをクエリする場合に非常に便利です(1
)一連のアクターの中で:
SELECT * FROM eg_assoc WHERE actors && '{1}'::int[]
ただし 、クエリのロジックは逆で、eg_assoc
の配列にリストされているすべての人を検索します。 。 GINインデックスはいいえです ここで助けてください。 PK person.id
のbtreeインデックスが必要です。 。
適切なクエリ
基本:
次のクエリは、元の配列を指定どおりに保持します。 、重複する可能性のある要素と要素の元の順序を含みます。 1次元配列で機能します 。追加のディメンションは1つのディメンションに折りたたまれます。複数のディメンションを保持することはより複雑です(ただし、完全に可能です):
WITH ORDINALITY
Postgres9.4以降
SELECT aid, actors
, ARRAY(SELECT name
FROM unnest(e.actors) WITH ORDINALITY a(id, i)
JOIN eg_person p USING (id)
ORDER BY a.i) AS act_names
, benefactors
, ARRAY(SELECT name
FROM unnest(e.benefactors) WITH ORDINALITY b(id, i)
JOIN eg_person USING (id)
ORDER BY b.i) AS ben_names
FROM eg_assoc e;
LATERAL
クエリ
PostgreSQLの場合9.3+ 。
SELECT e.aid, e.actors, a.act_names, e.benefactors, b.ben_names
FROM eg_assoc e
, LATERAL (
SELECT ARRAY( SELECT name
FROM generate_subscripts(e.actors, 1) i
JOIN eg_person p ON p.id = e.actors[i]
ORDER BY i)
) a(act_names)
, LATERAL (
SELECT ARRAY( SELECT name
FROM generate_subscripts(e.benefactors, 1) i
JOIN eg_person p ON p.id = e.benefactors[i]
ORDER BY i)
) b(ben_names);
db <> fiddle こちら
いくつかのバリエーションがあります。
古い
微妙な詳細:人が見つからない場合は、ドロップされます。これらのクエリは両方とも空の配列を生成します ( '{}'
)アレイ全体で人が見つからない場合。他のクエリスタイルはNULL
を返します 。フィドルにバリアントを追加しました。
関連するサブクエリ
Postgresの場合8.4+ (ここで、 generate_subsrcipts()
導入されました):
SELECT aid, actors
, ARRAY(SELECT name
FROM generate_subscripts(e.actors, 1) i
JOIN eg_person p ON p.id = e.actors[i]
ORDER BY i) AS act_names
, benefactors
, ARRAY(SELECT name
FROM generate_subscripts(e.benefactors, 1) i
JOIN eg_person p ON p.id = e.benefactors[i]
ORDER BY i) AS ben_names
FROM eg_assoc e;
Postgres 9.3でも、最高のパフォーマンスを発揮する可能性があります。
ARRAY
コンストラクター
array_agg()
よりも高速です 。参照:
失敗したクエリ
@a_horseが提供するクエリ そうです 仕事をするために、しかしそれは信頼性が低く、誤解を招き、潜在的に不正確で、不必要に高価です。
-
2つの無関係な結合のため、プロキシ相互結合。卑劣なアンチパターン。参照:
DISTINCT
で表面的に修正されましたarray_agg()
内 生成された重複を排除しますが、それは本当に豚に口紅をつけています。また、オリジナルの重複を排除します この時点で違いを区別することは不可能であるため、これは潜在的に正しくありません。 -
式
a_person.id = any(eg_assoc.actors)
動作 、ただし重複を排除 結果から(このクエリでは2回発生します)、指定しない限り間違っています。 -
元の配列要素の順序は保持されません 。これは一般的に注意が必要です。しかし、このクエリでは、アクターとベネファクターが乗算されて再び区別されるため、悪化します。これは保証 任意の順序。
-
外側の
SELECT
に列エイリアスはありません その結果、列名が重複し、一部のクライアントが失敗します(エイリアスのないフィドルでは機能しません)。 -
min(actors)
およびmin(benefactors)
役に立たない。通常は、列をGROUP BY
に追加するだけです。 それらを偽造する代わりに。ただし、eg_assoc.aid
とにかくPK列です(GROUP BY
でテーブル全体をカバーします )、それも必要ありません。ただactors, benefactors
。
結果全体を集計することは、最初から時間と労力を浪費します。基本行を乗算しないよりスマートなクエリを使用すると、それらを集約して戻す必要がありません。