The answer to the main question
AFAIK, you cannot declare a variable of a polymorphic type without a variable or template parameter.
, : IN, INOUT OUT ANYELEMENT . (ab) :
CREATE OR REPLACE FUNCTION uniq1(ary ANYARRAY, v ANYELEMENT = NULL)
RETURNS anyarray AS
$func$
DECLARE
ret ary%TYPE := '{}';
some_var v%TYPE;
BEGIN
IF ary IS NULL THEN
RETURN NULL;
END IF;
FOREACH v IN ARRAY ary LOOP
IF NOT v = any(ret) THEN
ret := array_append(ret, v);
END IF;
END LOOP;
RETURN ret;
END
$func$ LANGUAGE plpgsql;
:
DECLARE . .
, : ANYELEMENT = NULL
( ):
SELECT uniq1('{1,2,1}'::int[]);
SELECT uniq1('{foo,bar,bar}'::text[]);
OUT :
CREATE OR REPLACE FUNCTION uniq2(ary ANYARRAY, elem ANYELEMENT = NULL
, OUT ret ANYARRAY)
RETURNS anyarray AS
$func$
BEGIN
IF ary IS NULL
THEN RETURN;
ELSE ret := '{}'; -- init
END IF;
FOREACH elem IN ARRAY ary LOOP
IF elem = ANY(ret) THEN -- do nothing
ELSE
ret := array_append(ret, elem);
END IF;
END LOOP;
END
$func$ LANGUAGE plpgsql;
, NULL.
NULL:
CREATE OR REPLACE FUNCTION uniq3(ary ANYARRAY, elem ANYELEMENT = NULL
, OUT ret ANYARRAY)
RETURNS anyarray AS
$func$
BEGIN
IF ary IS NULL
THEN RETURN;
ELSE ret := '{}'; -- init
END IF;
FOREACH elem IN ARRAY ary LOOP
IF elem IS NULL THEN -- special test for NULL
IF array_length(array_remove(ret, NULL), 1) = array_length(ret, 1) THEN
ret := array_append(ret, NULL);
END IF;
ELSIF elem = ANY(ret) THEN -- do nothing
ELSE
ret := array_append(ret, elem);
END IF;
END LOOP;
END
$func$ LANGUAGE plpgsql;
NULL - :
. . :
SQL
Postgres 9.4 WITH ORDINALITY, .
:
:
SELECT ARRAY (
SELECT elem
FROM (
SELECT DISTINCT ON (elem) elem, i
FROM unnest('{1,2,1,NULL,4,NULL}'::int[]) WITH ORDINALITY u(elem, i)
ORDER BY elem, i
) sub
ORDER BY i) AS uniq;
:
uniq
------------
{1,2,NULL,4}
DISTINCT ON:
:
SELECT *
FROM test t
, LATERAL (
SELECT ARRAY (
SELECT elem
FROM (
SELECT DISTINCT ON (elem) elem, i
FROM unnest(t.arr) WITH ORDINALITY u(elem, i)
ORDER BY elem, i
) sub
ORDER BY i) AS arr
) a;
: NULL. :
SELECT t.*, CASE WHEN t.arr IS NULL THEN NULL ELSE a.arr END AS arr
FROM test t
, LATERAL (
SELECT ARRAY (
SELECT elem
FROM (
SELECT DISTINCT ON (elem) elem, ord
FROM unnest(t.arr) WITH ORDINALITY u(elem, ord)
ORDER BY elem, ord
) sub
ORDER BY ord) AS arr
) a;
:
SELECT *
FROM test t
LEFT JOIN LATERAL (
SELECT ARRAY (
SELECT elem
FROM (
SELECT DISTINCT ON (elem) elem, i
FROM unnest(t.arr) WITH ORDINALITY u(elem, i)
ORDER BY elem, i
) sub
ORDER BY i) AS arr
) a ON t.arr IS NOT NULL;
Postgres 9.3 generate_subscripts():
SELECT *
FROM test t
, LATERAL (
SELECT ARRAY (
SELECT elem
FROM (
SELECT DISTINCT ON (t.arr[i]) t.arr[i] AS elem, i
FROM generate_subscripts(t.arr, 1) i
ORDER BY t.arr[i], i
) sub
ORDER BY i
) AS arr
) a;
sqlfiddle, pg 9.3, WITH ORDINALITY :
SQL Fiddle.