如何将函数应用于Postgres中数组列的每个元素?

pun*_*ish 48 arrays postgresql

Pg查询返回一个数组.我想检索每个元素格式化为3位小数.如何将函数应用于数组的每个元素?像下面的东西(显然是错的) -

SELECT Round(ARRAY[1.53224,0.23411234], 2);
{1.532, 0.234}
Run Code Online (Sandbox Code Playgroud)

我想我正在寻找像Perl这样的map功能.

Joe*_*ams 97

首先,使用unnest将数组转换为集合:

> SELECT n FROM unnest(ARRAY[1.53224,0.23411234]) AS n;
     n      
------------
    1.53224
 0.23411234
(2 rows)
Run Code Online (Sandbox Code Playgroud)

然后,将表达式应用于列:

> SELECT ROUND(n, 2) FROM unnest(ARRAY[1.53224,0.23411234]) AS n;
 round 
-------
  1.53
  0.23
(2 rows)
Run Code Online (Sandbox Code Playgroud)

最后,使用array_agg将集合转换回数组:

> SELECT array_agg(ROUND(n, 2)) FROM unnest(ARRAY[1.53224,0.23411234]) AS n;
  array_agg  
-------------
 {1.53,0.23}
(1 row)
Run Code Online (Sandbox Code Playgroud)

  • 这是最简洁的解决方案,我喜欢你构建它的清晰方式. (6认同)
  • 如果您关心阵列的顺序,这是不安全的。虽然PostgreSQL目前不会重新排序此结果,但将来可以根据SQL规范免费这样做。您**必须**将“ unnest ...”与常规功能配合使用(9.4+) (4认同)
  • 你可以将它包装到用户定义的`round(int [],int)`函数中. (3认同)

Pav*_*ule 29

postgres=# select array(select round(unnest(array[1.2,2.4,3,4])));
   array   
-----------
{1,2,3,4}
(1 row)
Run Code Online (Sandbox Code Playgroud)

  • @PeterKrauss我现在做了基准测试,速度也一样 (2认同)
  • 请注意,对于空输入数组,arrag_agg() 返回 NULL,而 array() 返回空数组。 (2认同)

mas*_*sk8 15

您可能需要创建存储函数.这是你需要的东西:

CREATE OR REPLACE FUNCTION array_round(float[], int)
RETURNS float[]
AS
$$
DECLARE
   arrFloats ALIAS FOR $1;
   roundParam ALIAS FOR $2;
   retVal float[];
BEGIN
   FOR I IN array_lower(arrFloats, 1)..array_upper(arrFloats, 1) LOOP
    retVal[I] := round(CAST(arrFloats[I] as numeric), roundParam);
   END LOOP;
RETURN retVal;
END;
$$
LANGUAGE plpgsql 
   STABLE 
RETURNS NULL ON NULL INPUT;
Run Code Online (Sandbox Code Playgroud)

然后调用这样的东西:

# SELECT array_round(ARRAY[1.53224,0.23411234], 2);
 array_round 
-------------
 {1.53,0.23}
(1 row)
Run Code Online (Sandbox Code Playgroud)