Tengo una matriz de tipo bigint
, ¿cómo puedo eliminar los valores duplicados en esa matriz?
Ex: array[1234, 5343, 6353, 1234, 1234]
Debería conseguir array[1234, 5343, 6353, ...]
Probé el ejemplo SELECT uniq(sort('{1,2,3,2,1}'::int[]))
en el manual de postgres pero no funciona.
postgresql
GVK
fuente
fuente
trim(string_agg(distinct to_char(z.dat_codigo,'0000000000'),'')) as dat_codigo,
Las funciones
sort(int[])
yuniq(int[])
las proporciona el módulo contrib de intarray .Para habilitar su uso, debe instalar el módulo .
Si no desea utilizar el módulo contrib de intarray, o si tiene que eliminar duplicados de matrices de diferente tipo, tiene otras dos formas.
Si tiene al menos PostgreSQL 8.4, podría aprovechar la
unnest(anyarray)
funciónSELECT ARRAY(SELECT DISTINCT UNNEST('{1,2,3,2,1}'::int[]) ORDER BY 1); ?column? ---------- {1,2,3} (1 row)
Alternativamente, puede crear su propia función para hacer esto
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$;
Aquí hay una invocación de muestra:
SELECT array_sort_unique('{1,2,3,2,1}'::int[]); array_sort_unique ------------------- {1,2,3} (1 row)
fuente
... ¿Dónde están las bibliotecas estándar (?) Para este tipo de utilidad array_X ??
Intente buscar ... Ver algunos, pero no estándar:
postgres.cz/wiki/Array_based_functions : ¡buena referencia!
JDBurnZ / postgresql-anyarray , buena iniciativa pero necesita algo de colaboración para mejorar.
wiki.postgresql.org/Snippets , iniciativa frustrada, pero "wiki oficial", necesita algo de colaboración para mejorar.
MADlib : ¡bien! .... pero es un elefante, no una "librería de fragmentos de SQL puro".
La
array_distinct()
función snippet-lib más simple y rápidaAquí la implementación más simple y quizás más rápida para
array_unique()
oarray_distinct()
:CREATE FUNCTION array_distinct(anyarray) RETURNS anyarray AS $f$ SELECT array_agg(DISTINCT x) FROM unnest($1) t(x); $f$ LANGUAGE SQL IMMUTABLE;
NOTA: funciona como se esperaba con cualquier tipo de datos, excepto con una matriz de matrices,
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}"
el "efecto secundario" es descomponer todas las matrices en un conjunto de elementos.
PD: con matrices JSONB funciona bien,
SELECT array_distinct( array['[3,3]'::JSONB, '[3,3]'::JSONB, '[5,6]'::JSONB] ); -- "{"[3, 3]","[5, 6]"}"
Editar: más complejo pero útil, un parámetro "eliminar nulos"
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;
fuente
He reunido un conjunto de procedimientos almacenados (funciones) para combatir la falta de manejo de matrices de PostgreSQL
anyarray
. Estas funciones están diseñadas para funcionar en cualquier tipo de datos de matriz, no solo con números enteros como lo hace intarray: https://www.github.com/JDBurnZ/anyarrayEn su caso, todo lo que realmente necesita es
anyarray_uniq.sql
. Copie y pegue el contenido de ese archivo en una consulta de PostgreSQL y ejecútelo para agregar la función. Si también necesita ordenar matrices, agregue tambiénanyarray_sort.sql
.A partir de ahí, puede realizar una consulta simple de la siguiente manera:
SELECT ANYARRAY_UNIQ(ARRAY[1234,5343,6353,1234,1234])
Devuelve algo similar a:
ARRAY[1234, 6353, 5343]
O si necesita ordenar:
SELECT ANYARRAY_SORT(ANYARRAY_UNIQ(ARRAY[1234,5343,6353,1234,1234]))
Devolver exactamente:
ARRAY[1234, 5343, 6353]
fuente
El uso
DISTINCT
ordena implícitamente la matriz. Si es necesario conservar el orden relativo de los elementos de la matriz mientras se eliminan los duplicados, la función se puede diseñar de la siguiente manera: (debería funcionar desde 9.4 en adelante)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;
fuente
Esta es la forma "en línea":
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;
Primero creamos un conjunto a partir de una matriz, luego seleccionamos solo entradas distintas y luego lo agregamos nuevamente a la matriz.
fuente
SELECT array_agg(DISTINCT c1) FROM unnest(ARRAY[1234,5343,6353,1234,1234]) t(c1)
En una sola consulta hice esto:
SELECT (select array_agg(distinct val) from ( select unnest(:array_column) as val ) as u ) FROM :your_table;
fuente
Para personas como yo que todavía tienen que lidiar con postgres 8.2, esta función recursiva puede eliminar duplicados sin alterar la clasificación de la matriz
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;
por ejemplo :
select my_array_uniq(array[3,3,8,2,6,6,2,3,4,1,1,6,2,2,3,99]);
daré
fuente