这是我(可能通常适合你)非优化解决方案:
使用非优化内部函数的PG问题的解决方法:
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()
函数提供了对“内部行计数器”的直接访问,但它是关于行的,不是关于数组,不幸的是性能更差。
答案 0 :(得分:6)
PostgreSQL 为generate array subscripts提供专用功能:
WITH x(a) AS ( VALUES ('{1,20,3,5}'::int[]) )
SELECT generate_subscripts(a, 1) AS idx
,unnest(a) AS val
FROM x;
实际上它与@Frank的查询几乎相同,只是没有子查询
此外,它适用于不以1
开头的下标。
这两个解决方案仅适用于 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,20,3,5}'::int[]);
还要考虑:
SELECT * FROM unnest_with_idx('[4:7]={1,20,3,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) - 正如预期的那样,因为子查询。
除非您使用非标准索引下标,否则请使用新的 WITH ORDINALITY
:
答案 1 :(得分:1)
row_number()有效:
SELECT
row_number() over(),
value
FROM (SELECT unnest(array[1,20,3,5])) a(value);
然后,优化的功能将是
CREATE OR REPLACE FUNCTION unnest_with_idx(anyarray)
RETURNS table(idx integer, val anyelement) AS $$
SELECT (row_number() over())::integer as idx, val
FROM (SELECT unnest($1)) a(val);
$$ LANGUAGE SQL IMMUTABLE;