2つの配列の間で一致しない要素のみを選択する方法を教えてください。2つの配列を比較し、一致しない要素のみをポストグルで選択する方法
例:だからここに私は両方の配列を比較し、ベース・アレイからのマッチング要素を削除したい
base_array [12,3,5,7,8]
temp_array [3,7,8]
。
は今base_arrayは[12,5]
2つの配列の間で一致しない要素のみを選択する方法を教えてください。2つの配列を比較し、一致しない要素のみをポストグルで選択する方法
例:だからここに私は両方の配列を比較し、ベース・アレイからのマッチング要素を削除したい
base_array [12,3,5,7,8]
temp_array [3,7,8]
。
は今base_arrayは[12,5]
ようにする必要がありcontrib/intarrayモジュールは、この機能を提供 - 整数の配列のために、とにかく。他のデータ型については、独自の関数を記述したり、intarrayで提供されている関数を変更する必要があります。
select array_agg(elements)
from (
select unnest(array[12,3,5,7,8])
except
select unnest(array[3,7,8])
) t (elements)
私は配列演算子でこれにアプローチします。
select array(select unnest(:arr1) except select unnest(:arr2));
arr1と:arr2が交差しない場合、array_agg()を使用するとnullになります。
)のは(アンネストを試してみましょう/除い:
EXPLAIN ANALYZE SELECT array(select unnest(ARRAY[1,2,3,n]) EXCEPT SELECT unnest(ARRAY[2,3,4,n])) FROM generate_series(1,10000) n;
Function Scan on generate_series n (cost=0.00..62.50 rows=1000 width=4) (actual time=1.373..140.969 rows=10000 loops=1)
SubPlan 1
-> HashSetOp Except (cost=0.00..0.05 rows=1 width=0) (actual time=0.011..0.011 rows=1 loops=10000)
-> Append (cost=0.00..0.04 rows=2 width=0) (actual time=0.002..0.008 rows=8 loops=10000)
-> Subquery Scan "*SELECT* 1" (cost=0.00..0.02 rows=1 width=0) (actual time=0.002..0.003 rows=4 loops=10000)
-> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.001..0.002 rows=4 loops=10000)
-> Subquery Scan "*SELECT* 2" (cost=0.00..0.02 rows=1 width=0) (actual time=0.001..0.003 rows=4 loops=10000)
-> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.001..0.002 rows=4 loops=10000)
Total runtime: 142.531 ms
そしてintarray特別なオペレータ:
EXPLAIN ANALYZE SELECT ARRAY[1,2,3,n] - ARRAY[2,3,4,n] FROM generate_series(1,10000) n;
Function Scan on generate_series n (cost=0.00..15.00 rows=1000 width=4) (actual time=1.338..11.381 rows=10000 loops=1)
Total runtime: 12.306 ms
ベースライン:
EXPLAIN ANALYZE SELECT ARRAY[1,2,3,n], ARRAY[2,3,4,n] FROM generate_series(1,10000) n;
Function Scan on generate_series n (cost=0.00..12.50 rows=1000 width=4) (actual time=1.357..7.139 rows=10000 loops=1)
Total runtime: 8.071 ms
配列の交差点あたりの時間:
intarray - : 0.4 µs
unnest()/intersect : 13.4 µs
0私はセットを構築してきました。もちろん、
intarray方法がはるかに高速ですが、私はそれは素晴らしいPostgresは13.4マイクロ秒に(ハッシュや他のものが含まれている)に依存するサブクエリを攻撃することができますを見つける...
https://github.com/JDBurnZ/anyarray
これらの機能は、すべてのデータ型で機能しますが、整数型ではなく、intarray
に限定されています。GitHubのからこれらのSQLファイルで定義された関数をロードするロードした後
、あなたがする必要があるだろう、すべてがある:に似
SELECT
ANYARRAY_DIFF(
ARRAY[12, 3, 5, 7, 8],
ARRAY[3, 7, 8]
)
戻り何か:ARRAY[12, 5]
あなたも返却する必要がある場合ソート値:正確
SELECT
ANYARRAY_SORT(
ANYARRAY_DIFF(
ARRAY[12, 3, 5, 7, 8],
ARRAY[3, 7, 8]
)
)
戻り値:ARRAY[5, 12]
偉大な仕事!共有いただきありがとうございます! –
@a_horse_with_no_nameによって記載されているように私は、ロジックを除いて同じを使用して関数を作成します。
CREATE FUNCTION array_subtract(a1 int[], a2 int[]) RETURNS int[] AS $$
DECLARE
ret int[];
BEGIN
IF a1 is null OR a2 is null THEN
return a1;
END IF;
SELECT array_agg(e) INTO ret
FROM (
SELECT unnest(a1)
EXCEPT
SELECT unnest(a2)
) AS dt(e);
RETURN ret;
END;
$$ language plpgsql;
を次に、あなたがそれに応じてbase_array変数を変更するには、この機能を使用することができます。
base_array := array_subtract(base_array, temp_array);
配列の順序が異なる生成(ARRAY ['1'、 '2']))は空リストを返しますが、配列を選択します(ARRAY ['1'、 '2']) '])は、{2}を返します。 – Brady
@ブラディ:それは必要ですか? '{1} - {1,2} = {}'、 '{1,2} - {1} = {2}'です。 –
この関数が安定していないことを強調すると、 ':arr1'の順序は保持されません。この1つのライナーを共有していただきありがとうございます。 – jlandercy