Normalice los subíndices de la matriz para una matriz de 1 dimensión, de modo que comiencen con 1

PostgreSQL puede funcionar con subíndices de matriz que comiencen en cualquier lugar.
Considere este ejemplo que crea una matriz con 3 elementos con subíndices del 5 al 7:

SELECT ('[5:7]={1,2,3}'::int[]); 

Devoluciones:

 [5:7]={1,2,3} 

Es decir, por ejemplo, que obtienes el primer elemento con

 SELECT ('[5:7]={1,2,3}'::int[])[5]; 

Quiero normalizar cualquier matriz unidimensional dada para comenzar con el subíndice 1 de la matriz .
Lo mejor que se me ocurrió fue:

 SELECT ('[5:7]={1,2,3}'::int[])[array_lower('[5:7]={1,2,3}'::int[], 1):array_upper('[5:7]={1,2,3}'::int[], 1)] 

O, lo mismo, más fácil la lectura:

 WITH x(a) AS ( SELECT '[5:7]={1,2,3}'::int[] ) SELECT a[array_lower(a, 1):array_upper(a, 1)] FROM x 

¿Conoces una manera más simple / rápida o al menos más elegante?


Punto de referencia

Con el propósito de probar el rendimiento, elevé este punto de referencia rápido.
Tabla con 100k filas, matriz entera simple de longitud aleatoria entre 1 y 11:

 CREATE TEMP TABLE t (a int[]); INSERT INTO t -- now with actually varying subscripts SELECT ('[' || g%10 || ':' || 2*(g%10) || ']={1' || repeat(','||g::text, g%10) || '}')::int[] FROM generate_series(1,100000) g; EXPLAIN ANALYZE SELECT substring(a::text, '{.*$')::int[] -- Total runtime: 949.304 ms -- a[-2147483648:2147483647] -- Total runtime: 283.877 ms -- a[array_lower(a, 1):array_upper(a, 1)] -- Total runtime: 311.545 ms FROM t 

Entonces, sí, la idea de @ Daniel es un poco más rápida.
La conversión de texto de @ Kevin también funciona, pero no gana muchos puntos.

¿Alguna otra idea?

Hay un método más simple que es feo, pero creo que es técnicamente correcto: extrae la porción más grande posible de la matriz, a diferencia de la porción exacta con límites calculados. Evita las dos llamadas a funciones.

Ejemplo:

 select ('[5:7]={1,2,3}'::int[])[-2147483648:2147483647]; 

resultados en:

   int4   
 ---------
  {1,2,3}

No estoy seguro si esto ya está cubierto, pero:

 SELECT array_agg(v) FROM unnest('[5:7]={1,2,3}'::int[]) AS a(v); 

Para probar el rendimiento, tuve que agregar una columna de id en la tabla de prueba. Lento.

Eventualmente, algo más elegante apareció con Postgres 9.6 .
El manual:

Es posible omitir el lower-bound y / o upper-bound de un especificador de segmento; el límite perdido se reemplaza por el límite inferior o superior de los subíndices de la matriz. Por ejemplo:

Entonces es simple ahora:

 SELECT ('[5:7]={1,2,3}'::int[]) [:] ; 

Acerca del mismo rendimiento que la solución de Daniel con subíndices de matrices máximas codificadas , que todavía es el camino a seguir con Postgres 9.5 o anterior.