sql >> Base de Datos >  >> RDS >> PostgreSQL

Desanidar matriz por un nivel

Explicar

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

devuelve lo mismo que

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

que es NULO. Cito los documentos sobre ese asunto:

De forma predeterminada, el valor del índice de límite inferior de las dimensiones de una matriz se establece en uno.

0 no tiene un significado especial aquí. Además, con matrices bidimensionales, necesita dos índices para obtener un elemento base. Así:

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

Resultado:

2

La primera parte de su mensaje es un poco confusa.

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

Resultado:

[1:3][1:3]

Son dos dimensiones con 3 elementos (1 a 3) cada uno (9 elementos base).
Si quieres n-1 dimensiones entonces este es un resultado correcto:

SELECT ARRAY (SELECT unnest('{{1,2,3}, {4,5,6}, {7,8,9}}'::int[]))

Resultado:

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

Ese es uno dimensión. unnest() siempre produce un elemento base por fila. No estoy seguro de qué resultado desea exactamente. Su ejemplo es solo otra matriz bidimensional con un conjunto faltante de corchetes... ?

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

Si desea una parte de la matriz , prueba esta notación:

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

Resultado:

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

O esto:

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

Resultado:

{{4,5}}

Para aplanar el resultado (obtener una matriz 1D):

  • Cómo seleccionar una matriz 1d de una matriz 2d postgresql

Lea más en el manual aquí.

Función

Una prueba posterior reveló que esta función plpgsql es mucho más rápido. Requiere Postgres 9.1 o 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:

  • ¿Cómo anular una matriz 2d en una matriz 1d rápidamente en PostgreSQL?

Esta es una versión mejorada y simplificada de la función que Lukas publicó:

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 las versiones de Postgres <8.4, array_agg() no está instalado por defecto. Créalo primero:

CREATE AGGREGATE array_agg(anyelement) (
 SFUNC=array_append,
 STYPE=anyarray,
 INITCOND='{}'
);

Además, generate_subscripts() no ha nacido, todavía. Utilice en su lugar:

...
FROM   generate_series(array_lower($1,1), array_upper($1,1)) d1
    ,  generate_series(array_lower($1,2), array_upper($1,2)) d2
...

Llamar:

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

Resultado

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

Violín SQL.