タイプの配列がありbigint
ますが、その配列の重複する値を削除するにはどうすればよいですか?
例: array[1234, 5343, 6353, 1234, 1234]
私は得る必要があります array[1234, 5343, 6353, ...]
SELECT uniq(sort('{1,2,3,2,1}'::int[]))
postgresマニュアルで例をテストしましたが、機能していません。
回答:
私も同じように直面しました。しかし、私の場合の配列はarray_agg
関数を介して作成されます。そして幸いなことに、次のようなDISTINCT値を集約できます。
array_agg(DISTINCT value)
これは私にとってはうまくいきます。
trim(string_agg(distinct to_char(z.dat_codigo,'0000000000'),'')) as dat_codigo,
sort(int[])
そしてuniq(int[])
関数はによって提供されるintarrayのcontribモジュール。
使用できるようにするには、モジュールをインストールする必要があります。
intarray contribモジュールを使用したくない場合、または異なるタイプの配列から重複を削除する必要がある場合は、他に2つの方法があります。
少なくともPostgreSQL8.4を使用している場合は、unnest(anyarray)
機能を利用できます。
SELECT ARRAY(SELECT DISTINCT UNNEST('{1,2,3,2,1}'::int[]) ORDER BY 1);
?column?
----------
{1,2,3}
(1 row)
または、これを行うための独自の関数を作成することもできます
CREATE OR REPLACE FUNCTION array_sort_unique (ANYARRAY) RETURNS ANYARRAY
LANGUAGE SQL
AS $body$
SELECT ARRAY(
SELECT DISTINCT $1[s.i]
FROM generate_series(array_lower($1,1), array_upper($1,1)) AS s(i)
ORDER BY 1
);
$body$;
呼び出しの例を次に示します。
SELECT array_sort_unique('{1,2,3,2,1}'::int[]);
array_sort_unique
-------------------
{1,2,3}
(1 row)
...この種のarray_Xユーティリティの標準ライブラリ(?)はどこにありますか?
検索してみてください...いくつかの標準を参照してください。
postgres.cz/wiki/Array_based_functions:良いリファレンスです!
JDBurnZ / postgresql-anyarray、優れたイニシアチブですが、強化するにはいくつかのコラボレーションが必要です。
wiki.postgresql.org/Snippets、欲求不満のイニシアチブ、しかし「公式ウィキ」は、強化するためにいくつかのコラボレーションが必要です。
MADlib:いいね!....しかし、それは象であり、「純粋なSQLスニペットライブラリ」ではありません。
array_distinct()
スニペット-lib関数ここでは、array_unique()
またはの最も単純でおそらくより高速な実装ですarray_distinct()
。
CREATE FUNCTION array_distinct(anyarray) RETURNS anyarray AS $f$
SELECT array_agg(DISTINCT x) FROM unnest($1) t(x);
$f$ LANGUAGE SQL IMMUTABLE;
注:配列の配列を除くすべてのデータ型で期待どおりに機能します。
SELECT array_distinct( array[3,3,8,2,6,6,2,3,4,1,1,6,2,2,3,99] ),
array_distinct( array['3','3','hello','hello','bye'] ),
array_distinct( array[array[3,3],array[3,3],array[3,3],array[5,6]] );
-- "{1,2,3,4,6,8,99}", "{3,bye,hello}", "{3,5,6}"
「副作用」は、要素のセット内のすべての配列を爆発させることです。
PS:JSONB配列を使用すると、正常に機能します。
SELECT array_distinct( array['[3,3]'::JSONB, '[3,3]'::JSONB, '[5,6]'::JSONB] );
-- "{"[3, 3]","[5, 6]"}"
編集:より複雑ですが便利な「ドロップヌル」パラメータ
CREATE FUNCTION array_distinct(
anyarray, -- input array
boolean DEFAULT false -- flag to ignore nulls
) RETURNS anyarray AS $f$
SELECT array_agg(DISTINCT x)
FROM unnest($1) t(x)
WHERE CASE WHEN $2 THEN x IS NOT NULL ELSE true END;
$f$ LANGUAGE SQL IMMUTABLE;
PostgreSQLの配列処理の欠如に対処するために、一連のストアドプロシージャ(関数)を組み立てましたanyarray
。これらの関数は、intarrayのように整数だけでなく、任意の配列データ型で機能するように設計されています:https://www.github.com/JDBurnZ/anyarray
あなたの場合、本当に必要なのはanyarray_uniq.sql
です。そのファイルの内容をコピーしてPostgreSQLクエリに貼り付け、実行して関数を追加します。配列の並べ替えも必要な場合は、も追加しanyarray_sort.sql
ます。
そこから、次のように簡単なクエリを実行できます。
SELECT ANYARRAY_UNIQ(ARRAY[1234,5343,6353,1234,1234])
次のようなものを返します。 ARRAY[1234, 6353, 5343]
または、並べ替えが必要な場合:
SELECT ANYARRAY_SORT(ANYARRAY_UNIQ(ARRAY[1234,5343,6353,1234,1234]))
正確に返す: ARRAY[1234, 5343, 6353]
を使用するとDISTINCT
、配列が暗黙的にソートされます。重複を削除するときに配列要素の相対的な順序を保持する必要がある場合、関数は次のように設計できます:( 9.4以降で機能するはずです)
CREATE OR REPLACE FUNCTION array_uniq_stable(anyarray) RETURNS anyarray AS
$body$
SELECT
array_agg(distinct_value ORDER BY first_index)
FROM
(SELECT
value AS distinct_value,
min(index) AS first_index
FROM
unnest($1) WITH ORDINALITY AS input(value, index)
GROUP BY
value
) AS unique_input
;
$body$
LANGUAGE 'sql' IMMUTABLE STRICT;
これが「インライン」の方法です。
SELECT 1 AS anycolumn, (
SELECT array_agg(c1)
FROM (
SELECT DISTINCT c1
FROM (
SELECT unnest(ARRAY[1234,5343,6353,1234,1234]) AS c1
) AS t1
) AS t2
) AS the_array;
最初に配列からセットを作成し、次に個別のエントリのみを選択して、それを配列に集約します。
SELECT array_agg(DISTINCT c1) FROM unnest(ARRAY[1234,5343,6353,1234,1234]) t(c1)
単一のクエリで私はこれを行いました:
SELECT (select array_agg(distinct val) from ( select unnest(:array_column) as val ) as u ) FROM :your_table;
まだpostgres8.2に対処しなければならない私のような人々にとって、この再帰関数は配列のソートを変更することなく重複を排除することができます
CREATE OR REPLACE FUNCTION my_array_uniq(bigint[])
RETURNS bigint[] AS
$BODY$
DECLARE
n integer;
BEGIN
-- number of elements in the array
n = replace(split_part(array_dims($1),':',2),']','')::int;
IF n > 1 THEN
-- test if the last item belongs to the rest of the array
IF ($1)[1:n-1] @> ($1)[n:n] THEN
-- returns the result of the same function on the rest of the array
return my_array_uniq($1[1:n-1]);
ELSE
-- returns the result of the same function on the rest of the array plus the last element
return my_array_uniq($1[1:n-1]) || $1[n:n];
END IF;
ELSE
-- if array has only one item, returns the array
return $1;
END IF;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
例えば :
select my_array_uniq(array[3,3,8,2,6,6,2,3,4,1,1,6,2,2,3,99]);
あげる
{3,8,2,6,4,1,99}