sexta-feira, 17 de setembro de 2010

Função "array_diff" em PostgreSQL

Estava realizando algumas queries aqui no meu trabalho e tive a necessidade de uma função que retornasse um array contendo os elementos de um determinado array e não estão presentes em outro, igual ao array_diff do PHP [1].

Para resolver esse pequeno problema bastou um SELECT, vejam a implementação da função "array_diff" para PostgreSQL abaixo:

CREATE OR REPLACE FUNCTION array_diff (anyarray, anyarray) RETURNS anyarray
AS $$
  SELECT array(
    SELECT $1[s.i]
      FROM generate_series(array_lower($1,1), array_upper($1,1)) AS s(i)
     WHERE NOT $1[s.i] = ANY($2)
  );
$$
LANGUAGE sql;

postgres@bdteste=# SELECT array_diff(array[1, 2, 3], array[1, 4, 3]);
 array_diff
------------
 {2}
(1 row)

postgres@bdteste=# SELECT array_diff(array[1, 4, 3], array[1, 2, 3]);
 array_diff
------------
 {4}
(1 row)


Espero ter ajudado de alguma forma.



Cordialmente,

Fabrízio de Royes Mello
fabriziomello [at] gmail.com

2 comentários:

  1. Opa amigo, Eu estava procurando uma forma de fazer o diff e depois que vi como vc fez eu resolvi usar a funcao unnest e fiz desta forma, nao sei se ficou melhor ou pior...
    Grande abraço e obrigado pela luz ;)

    CREATE OR REPLACE FUNCTION arrayDiff(anyarray, anyarray) RETURNS anyarray
    AS $$
    SELECT array(
    SELECT x
    FROM unnest($1) AS x WHERE x not in (SELECT unnest($2))
    );
    $$
    LANGUAGE sql;

    ResponderExcluir
  2. Sua refatoração é muito válida, porém sacrificamos a portabilidade da função... a versão que implementei funciona com as versões 8.1, 8.2, 8.3, 8.4, 9.0 e 9.1 (q ainda esta em beta).

    A utilização da função "unnest" limita vc a utilizar a função somente em versões iguais ou superiores a 8.4.

    De qualquer forma ficou muito enxuta a versão que vc implemento... gostei bastante.


    Fabrízio de Royes Mello
    fabriziomello [at] gmail.com

    ResponderExcluir