PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Desaninhar array em um nível

Explicar

SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[0]

retorna o mesmo que
SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[17]

que é NULO. Cito os documentos sobre o assunto:

Por padrão, o valor do índice do limite inferior das dimensões de uma matriz é definido como um.

0 não tem nenhum significado especial aqui. Além disso, com arrays bidimensionais, você precisa de dois índices para obter um elemento base. Assim:
SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[1][2]

Resultado:
2

A primeira parte da sua mensagem é um pouco obscura.
SELECT array_dims(ARRAY[[1,2,3], [4,5,6], [7,8,9]])

Resultado:
[1:3][1:3]

São dois dimensões com 3 elementos (1 a 3) cada (9 elementos base).
Se você quiser n-1 dimensões, então este é um resultado correto:
SELECT ARRAY (SELECT unnest('{{1,2,3}, {4,5,6}, {7,8,9}}'::int[]))

Resultado:
{1,2,3,4,5,6,7,8,9}

Isso é um dimensão. unnest() sempre produz um elemento base por linha. Não tenho certeza de qual resultado você deseja exatamente. Seu exemplo é apenas outra matriz bidimensional com um conjunto ausente de colchetes ... ?
{1,2,3}, {4,5,6}, {7,8,9}

Se você quiser uma fatia da matriz , tente esta notação:
SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[1:2]

Resultado:
{{1,2,3},{4,5,6}}

Ou isto:
SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[2:2][1:2]

Resultado:
{{4,5}}

Para achatar o resultado (obtenha uma matriz 1D):
  • Como selecionar uma matriz 1d de uma matriz 2d postgresql

Leia mais no manual aqui.

Função


Testes posteriores revelaram que esta função plpgsql é muito mais rápido. Requer Postgres 9.1 ou posterior:
CREATE OR REPLACE FUNCTION unnest_2d_1d(ANYARRAY, OUT a ANYARRAY)
  RETURNS SETOF ANYARRAY AS
$func$
BEGIN
   FOREACH a SLICE 1 IN ARRAY $1 LOOP
      RETURN NEXT;
   END LOOP;
END
$func$  LANGUAGE plpgsql IMMUTABLE;

Ver:
  • Como desaninhar um array 2d em um array 1d rapidamente no PostgreSQL?

Esta é uma versão melhorada e simplificada da função que Lukas postou:
CREATE OR REPLACE FUNCTION unnest_2d_1d(anyarray)
  RETURNS SETOF anyarray AS
$func$
SELECT array_agg($1[d1][d2])
FROM   generate_subscripts($1,1) d1
    ,  generate_subscripts($1,2) d2
GROUP  BY d1
ORDER  BY d1
$func$  LANGUAGE sql IMMUTABLE;

Para versões do Postgres <8.4, array_agg() não é instalado por padrão. Crie primeiro:
CREATE AGGREGATE array_agg(anyelement) (
 SFUNC=array_append,
 STYPE=anyarray,
 INITCOND='{}'
);

Além disso, generate_subscripts() ainda não nasceu. Use em vez disso:
...
FROM   generate_series(array_lower($1,1), array_upper($1,1)) d1
    ,  generate_series(array_lower($1,2), array_upper($1,2)) d2
...

Ligar:
SELECT unnest_2d_1d(ARRAY[[1,2], [3,4], [5,6]]);

Resultado
{1,2}
{3,4}
{5,6}

SQL Fiddle.