根据数组中的位置乘以数组中的元素

时间:2014-05-26 23:28:35

标签: sql arrays postgresql set-returning-functions

我可以使用什么有效的函数来增加数组中元素的位置?

例如,如果我有一个数组:

ARRAY[10,20,30,40,50]::INT[]

我希望转变为:

ARRAY[10,20,20,30,30,30,40,40,40,40,50,50,50,50,50]::INT[]

所以我有1“10”,2“20”,3“30”,4“40”和5“50”。

对于数组:

ARRAY[10,20,30,40,10]::INT[]

我希望转变为:

ARRAY[10,20,20,30,30,30,40,40,40,40,10,10,10,10,10]::INT[]

所以我有6“10”,2“20”,3“30”和4“40”。

1 个答案:

答案 0 :(得分:3)

WITH t AS (SELECT ARRAY[10,20,30,40,50]::INT[] AS arr)   -- variable for demo
SELECT ARRAY(
   SELECT unnest(array_fill(arr[idx], ARRAY[idx])) AS mult
   FROM  (SELECT arr, generate_subscripts(arr, 1) AS idx FROM t) sub
   );

我会将逻辑包装成一个简单的IMMUTABLE SQL函数:

CREATE OR REPLACE FUNCTION f_expand_arr(_arr anyarray)
  RETURNS anyarray AS
$func$
SELECT ARRAY(
   SELECT unnest(array_fill(_arr[idx], ARRAY[idx]))
   FROM  (SELECT generate_subscripts(_arr, 1) AS idx) sub
   )
$func$ LANGUAGE sql IMMUTABLE;

由于多态参数类型anyarray,适用于任何基类型的数组:
How to write a function that returns text or integer values?

generate_subscripts()array_fill()上的手册。

注意:这适用于实际的数组索引,它可能与Postgres中的序数数组位置不同。您可能对@ Daniel的方法感兴趣,以及#34;规范化"数组索引:
Normalize array subscripts for 1-dimensional array so they start with 1

即将推出的Postgres 9.4(目前为测试版)提供WITH ORDINALITY
PostgreSQL unnest() with element number

允许这种更优雅和可靠的解决方案:

CREATE OR REPLACE FUNCTION f_expand_arr(_arr anyarray)
  RETURNS anyarray AS
$func$
SELECT ARRAY(
   SELECT unnest(array_fill(a, ARRAY[idx]))
   FROM   unnest(_arr) WITH ORDINALITY AS x (a, idx)
   )
$func$ LANGUAGE sql IMMUTABLE;

有人可能仍然认为正确的订单实际上不是保证。我声称这是...... Parallel unnest() and sort order in PostgreSQL

呼叫:

SELECT f_expand_arr(ARRAY[10,20,30,40,10]::INT[]) AS a2;

或表中的值:

SELECT f_expand_arr(a) AS a2 FROM t;

SQL Fiddle.