arrays - 将数组取消一级

标签 arrays postgresql plpgsql

我想获取一个 n 维度的数组,并返回包含 n-1 维度数组行的集合。例如,取数组 ARRAY[[1,2,3], [4,5,6], [7,8,9]] 并返回一个集合 {1,2 ,3}, {4,5,6}, {7,8,9}。使用 unnest 返回集合 1,2,3,4,5,6,7,8,9

我尝试从 PostgreSQL 8.4 中获取 unnest 函数,它似乎可以满足我的要求:

CREATE OR REPLACE FUNCTION tstng.unnest2(anyarray)
    RETURNS SETOF anyelement
    LANGUAGE plpgsql
    IMMUTABLE
    AS $$
    BEGIN
            RETURN QUERY SELECT $1[i]
                FROM generate_series(array_lower($1,1), array_upper($1,1)) i;
        END;
    $$;

但是,SELECT tstng.unnest2(ARRAY[[1,2,3], [4,5,6], [7,8,9]]); 返回集合 , ,(即:3 个空行)。

我还发现 SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[0]; 返回null,我认为这是我问题的根源。

最佳答案

函数

n 维数组中分解出一维数组 - 代表嵌套维度的叶子。 (n>= 1。)

PL/pgSQL

FOR loop遍历数组:

CREATE OR REPLACE FUNCTION unnest_nd_1d(a ANYARRAY, OUT a_1d ANYARRAY)
  RETURNS SETOF ANYARRAY
  LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE STRICT AS
$func$
BEGIN
   FOREACH a_1d SLICE 1 IN ARRAY a LOOP
      RETURN NEXT;
   END LOOP;
END
$func$;

SLICE 1 指示获取一维数组。 (SLICE 2 将采用二维数组。)

PARALLEL SAFE 仅适用于 Postgres 9.6 或更高版本。

后来的测试表明这个 PL/pgSQL 函数是最快的。
相关:

纯SQL

仅适用于二维数组:

CREATE OR REPLACE FUNCTION unnest_2d_1d(anyarray)
  RETURNS SETOF anyarray
  LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS
$func$
SELECT array_agg($1[d1][d2])
FROM   generate_subscripts($1,1) d1
    ,  generate_subscripts($1,2) d2
GROUP  BY d1
ORDER  BY d1
$func$;

这是 the function Lukas posted 的改进和简化版本.

db<> fiddle here
<子>旧sqlfiddle

说明

SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[0]

返回相同的:

SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[17]

... 这是 NULLThe manual :

By default, the lower bound index value of an array's dimensions is set to one.

0作为数组下标没有特殊意义。对于具有默认索引的 Postgres 数组,那里什么也没有。
此外,对于二维数组,您需要两个索引 来获取基本元素。喜欢:

SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[1][2]

结果:

2

您的消息的第一部分有点不清楚。

SELECT array_dims(ARRAY[[1,2,3], [4,5,6], [7,8,9]]);

结果:

[1:3][1:3]

这是二维维度,每个维度有 3 个元素(1 到 3)(9 个基本元素)。
如果您想要 n-1 维度,那么这是正确的结果:

SELECT ARRAY (SELECT unnest('{{1,2,3}, {4,5,6}, {7,8,9}}'::int[]))

结果:

{1,2,3,4,5,6,7,8,9}

这是一个维度。 unnest() 每行生成一个基本元素(无论数组维度如何)。您的示例只是另一个缺少大括号集的二维数组...?

{1,2,3}, {4,5,6}, {7,8,9}

如果你想要一个数组的切片:

SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[1:2]

结果:

{{1,2,3},{4,5,6}}

或者:

SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[2:2][1:2]

结果:

{{4,5}}

展平结果(获取一维数组):

Read the manual here.

对于非常旧的版本

对于 Postgres 版本 < 8.4,默认情况下不安装 array_agg()。先创建它:

CREATE AGGREGATE array_agg(anyelement) (
 SFUNC = array_append,
 STYPE = anyarray,
 INITCOND = '{}'
);

此外,generate_subscripts()还没有出生。改用:

...
FROM   generate_series(array_lower($1,1), array_upper($1,1)) d1
    ,  generate_series(array_lower($1,2), array_upper($1,2)) d2
...

调用:

SELECT unnest_2d_1d(ARRAY[[1,2], [3,4], [5,6]]);

结果

{1,2}
{3,4}
{5,6}

关于arrays - 将数组取消一级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8137112/

相关文章:

postgresql - 如何在 POSTGIS 中使用带重新投影的 st_intersection()?

php - 如何从其他数组中取出值

PHP:使用 "new"初始化数组与不使用 0x104567910 初始化数组有什么区别?

java - 如何在 Java 中反转数组?

c++ - 检索具有非常量变量的真值表的单行

PostgresQL 错误 : relation <table> doesn't exist

postgresql - postgres 插入带有选择大小写的表

function - 使用 execute (plpgsql) 创建一个函数

postgresql - 函数根据参数从两个查询之一返回记录集

sql - 函数中的临时表和循环