31

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

5 に答える 5

18

追加のモジュール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を使用することはできず、その逆も同様です。

関連している:

于 2012-10-13T06:14:40.957 に答える
14

最も簡単な方法は、それらを並べ替えて、並べ替えて比較することです。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 になります。

これらのアプローチは両方とも、パフォーマンスがかなり悪くなります。最初に配列を常に並べ替えて保存することを検討してください。

于 2012-10-13T05:15:32.867 に答える
0

配列に重複がなく同じ次元の場合:

  • 配列を使用@>
  • そしてarray_length、長さが両側で必要なサイズと一致する必要があります
于 2020-08-05T08:11:44.243 に答える