将数组取消一层 [英] Unnest array by one level

查看:73
本文介绍了将数组取消一层的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想获取一个 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.

I want to take an array of n dimensions and return set containing rows of arrays of n-1 dimensions. For example, take the array ARRAY[[1,2,3], [4,5,6], [7,8,9]] and return a set {1,2,3}, {4,5,6}, {7,8,9}. Using unnest returns the set 1,2,3,4,5,6,7,8,9.

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

I tried grabbing the unnest function from PostgreSQL 8.4, which seems like it would do what I'm looking for:

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 个空行).

However, SELECT tstng.unnest2(ARRAY[[1,2,3], [4,5,6], [7,8,9]]); returns the set , , (i.e.: 3 null rows).

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

I've also found that SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[0]; returns null, which I believe to be the root of my problem.

推荐答案

说明

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

返回与

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

为 NULL.我引用了关于此事的文档:

which is NULL. I quote the docs on that matter:

默认情况下,数组维度的下界索引值为设置为一.

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

0 在这里没有特殊意义.此外,对于二维数组,您需要两个索引来获取基本元素.像这样:

0 has no special meaning here. Also, with a two-dimensional arrays, you need two indexes to get a base element. Like this:

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

结果:

2

<小时>

您邮件的第一部分有点不清楚.


The first part of your message is a bit unclear.

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

结果:

[1:3][1:3]

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

That's two dimensions with 3 elements (1 to 3) each (9 base elements).
If you want n-1 dimensions then this is a correct result:

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

结果:

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

这是一个维度.unnest() 总是每行产生一个基本元素.我不确定你想要什么结果.您的示例只是另一个缺少一组大括号的二维数组......?

That's one dimension. unnest() always produces one base element per row. I am not sure what result you desire exactly . Your example is just another 2-dimenstional array with a missing set of curly brackets ... ?

{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}}

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

To flatten the result (get a 1D array):

阅读更多此处的手册.

后来的测试表明,这个 plpgsql 函数快得多.需要 Postgres 9.1 或更高版本:

Later test revealed that this plpgsql function is much faster. Requires Postgres 9.1 or later:

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

见:

这是Lukas 发布的函数的改进和简化版本:

This is an improved and simplified version of the function Lukas posted:

CREATE OR REPLACE FUNCTION unnest_2d_1d(anyarray)
  RETURNS SETOF anyarray 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$  LANGUAGE sql IMMUTABLE;

对于 Postgres 版本 <8.4、array_agg()默认没有安装.先创建:

For Postgres versions < 8.4, array_agg() is not installed by default. Create it first:

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

另外,generate_subscripts() 还没有出生.改用:

Also, generate_subscripts() is not born, yet. Use instead:

...
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}

SQL 小提琴.

这篇关于将数组取消一层的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆