4つの配列列を持つテーブルがあります。結果は次のようになります。
ids signed_ids new_ids new_ids_signed
{1,2,3} | {2,1,3} | {4,5,6} | {6,5,4}
とにかく、要素の順序を無視することによって、それらが等しくなるように比較ids
しますか?signed_ids
4つの配列列を持つテーブルがあります。結果は次のようになります。
ids signed_ids new_ids new_ids_signed
{1,2,3} | {2,1,3} | {4,5,6} | {6,5,4}
とにかく、要素の順序を無視することによって、それらが等しくなるように比較ids
しますか?signed_ids
追加のモジュールintarrayは、通常 (はるかに) 高速なの配列のinteger
演算子を提供します。データベースごとに 1 回インストールします (Postgres 9.1 以降の場合):
CREATE EXTENSION intarray;
次に、次のことができます。
SELECT uniq(sort(ids)) = uniq(sort(signed_ids));
または:
SELECT ids @> signed_ids AND ids <@ signed_ids;
intarray の関数と演算子を大胆に強調。
2 番目の例では、左右の引数が type の場合、演算子の解決は特殊な intarray 演算子に到達しますinteger[]
。
どちらの式も要素の順序と重複を無視します。詳しくは、こちらの役立つマニュアルをご覧ください。
intarray
演算子はinteger
( int4
) の配列に対してのみ機能し、bigint
( int8
) またはsmallint
( int2
) やその他のデータ型では機能しません。
デフォルトの汎用演算子とは異なり、intarray
演算子は配列で NULL 値を受け入れません。関連する配列に NULL があると、例外が発生します。NULL 値を使用する必要がある場合は、次の構文で演算子をスキーマ修飾することにより、標準のジェネリック演算子をデフォルトにすることができます。OPERATOR
SELECT ARRAY[1,4,null,3]::int[] OPERATOR(pg_catalog.@>) ARRAY[3,1]::int[]
ジェネリック演算子は、演算子クラスでインデックスintarray
を使用することはできず、その逆も同様です。
関連している:
最も簡単な方法は、それらを並べ替えて、並べ替えて比較することです。PostgreSQL での配列のソートを参照してください。
与えられたサンプルデータ:
CREATE TABLE aa(ids integer[], signed_ids integer[]);
INSERT INTO aa(ids, signed_ids) VALUES (ARRAY[1,2,3], ARRAY[2,1,3]);
Erwin が answer で説明しているように、配列エントリが常に整数である場合に最善の方法は、intarray 拡張機能を使用することです。純粋な SQL 形式よりもはるかに高速です。
それ以外の場合、任意のデータ型で機能する一般的なバージョンでは、次を定義しますarray_sort(anyarray)
。
CREATE OR REPLACE FUNCTION array_sort(anyarray) RETURNS anyarray AS $$
SELECT array_agg(x order by x) FROM unnest($1) x;
$$ LANGUAGE 'SQL';
並べ替えを使用して、並べ替えられた配列を比較します。
SELECT array_sort(ids) = array_sort(signed_ids) FROM aa;
重要な警告があります:
SELECT array_sort( ARRAY[1,2,2,4,4] ) = array_sort( ARRAY[1,2,4] );
偽になります。これは、意図に応じて、必要な場合とそうでない場合があります。
または、関数を定義しますarray_compare_as_set
。
CREATE OR REPLACE FUNCTION array_compare_as_set(anyarray,anyarray) RETURNS boolean AS $$
SELECT CASE
WHEN array_dims($1) <> array_dims($2) THEN
'f'
WHEN array_length($1,1) <> array_length($2,1) THEN
'f'
ELSE
NOT EXISTS (
SELECT 1
FROM unnest($1) a
FULL JOIN unnest($2) b ON (a=b)
WHERE a IS NULL or b IS NULL
)
END
$$ LANGUAGE 'SQL' IMMUTABLE;
その後:
SELECT array_compare_as_set(ids, signed_ids) FROM aa;
array_sort
これは、2 つのed 値を比較することとは微妙に異なります。array_compare_as_set
は重複を排除してarray_compare_as_set(ARRAY[1,2,3,3],ARRAY[1,2,3])
true にしますが、array_sort(ARRAY[1,2,3,3]) = array_sort(ARRAY[1,2,3])
は false になります。
これらのアプローチは両方とも、パフォーマンスがかなり悪くなります。最初に配列を常に並べ替えて保存することを検討してください。
配列に重複がなく、同じ次元の場合:
@>
array_length
、長さが両側で必要なサイズと一致する必要があります