标准化1维数组的数组下标,以1开头

PostgreSQL可以在任何地方使用数组下标。
考虑这个例子,它创build一个数组,其中包含3个下标5到7的元素:

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

返回:

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

意思是,例如,你得到第一个元素

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

我想规范 任何给定的1维数组开始数组下标1
最好的我可以拿出:

 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)] 

或者,相同,更容易阅读:

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

你知道更简单/更快或至less更优雅的方式吗?


基准

为了testing性能,我掀起了这个快速的基准。
100k行表,简单的整数数组,随机长度在1和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 

所以,是的,@丹尼尔的想法稍微快一点。
@凯文的文字转换作品也一样,但是赚不了多less分。

任何其他的想法?

有一个更简单的方法是丑陋的,但我相信技术上是正确的:从数组中提取出最大可能的切片,而不是具有计算边界的确切切片。 它避免了这两个函数调用。

例:

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

结果是:

   INT4   
 ---------
  {1,2,3}

不知道这是否已经被覆盖,但是:

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

为了testing性能,我必须在testing表上添加id列。 慢。

最终,Postgres 9.6 popup更优雅的东西 。
手册:

可以省略分片说明符的lower-bound和/或upper-bound ; 丢失的边界被数组下标的下限或上限替代。 例如:

所以现在很简单:

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

与Daniel提供的硬编码最大数组下标相同的性能 – 仍然是使用Postgres 9.5或更早版本的方法。