标准化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或更早版本的方法。