CREATE FUNCTION unnest_with_idx(anyarray) RETURNS TABLE(idx integer,val anyelement) AS $$ SELECT generate_series(1,array_upper($1,1)) as idx,unnest($1) as val; $$LANGUAGE sql IMMUTABLE;
测试:
SELECT idx,val from unnest_with_idx(array[1,20,3,5]) as t;
但是,正如我所说,非优化.我不敢相信(!!)Postgresql没有数组的内部索引……?但在这种情况下,问题是如何直接访问这个指数,GIN-like内部计数器在哪里?
注1:上述解决方案和问题与“how do you create an index by each element of an array?”不同.也与“Can PostgreSQL index array columns?”不同,因为该函数用于隔离数组,而不是用于数组字段的表索引.
NOTE2(在答案后编辑):“数组索引”(更常用的术语)或“数组下标”或“数组计数器”是我们可以在语义路径中用来引用“内部计数器”,累加器到下一个数组的术语项目.我看到没有Postgresql命令提供对此计数器的直接访问.作为generate_series()函数,generate_subscripts()函数是一个序列生成器,性能(最好但是)接近相同.另一方面,row_number()函数提供了对“行内部计数器”的直接访问,但它是关于行,而不是关于数组,不幸的是性能更差.
WITH x(a) AS ( VALUES ('{1,5}'::int[]) ) SELECT generate_subscripts(a,1) AS idx,unnest(a) AS val FROM x;
实际上它与@Frank的查询几乎相同,只是没有子查询.
此外,它适用于不以1开头的下标.
这两种解决方案都只适用于一维数组! (可以轻松扩展到多个维度.)
功能:
CREATE OR REPLACE FUNCTION unnest_with_idx(anyarray) RETURNS TABLE(idx integer,val anyelement) LANGUAGE sql IMMUTABLE AS $func$ SELECT generate_subscripts($1,1),unnest($1); $func$;
呼叫:
SELECT * FROM unnest_with_idx('{1,5}'::int[]);
还要考虑:
SELECT * FROM unnest_with_idx('[4:7]={1,5}'::int[]);
有关this related question中数组下标的更多信息.
如果你真的想要标准化的下标(从1开始),我会使用:
SELECT generate_series(1,array_length($1,1)) ...
这几乎是你已经拥有的查询,只是使用array_length()
而不是array_upper() – 这将使用非标准下标失败.
我对1000 int的数组进行了快速测试,目前为止所有查询都在这里.它们都执行大约相同的(~3.5 ms) – 除了子查询上的row_number()(~7,5 ms) – 正如预期的那样,因为子查询.
更新:Postgres 9.4
除非您使用非标准索引下标,否则请使用新的WITH ORDINALITY: