Unnest阵列一级

Mat*_*att 11 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中获取不需要的函数,这似乎就像我正在寻找的那样:

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;
    $$;
Run Code Online (Sandbox Code Playgroud)

但是,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,我认为这是我问题的根源.

Erw*_*ter 16

说明

SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[0]
Run Code Online (Sandbox Code Playgroud)

返回相同

SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[17]
Run Code Online (Sandbox Code Playgroud)

这是NULL.我引用有关此事文件:

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

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

SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[1][2]
Run Code Online (Sandbox Code Playgroud)

结果:

2
Run Code Online (Sandbox Code Playgroud)

你的信息的第一部分有点不清楚.

SELECT array_dims(ARRAY[[1,2,3], [4,5,6], [7,8,9]])
Run Code Online (Sandbox Code Playgroud)

结果:

[1:3][1:3]
Run Code Online (Sandbox Code Playgroud)

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

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

结果:

{1,2,3,4,5,6,7,8,9}
Run Code Online (Sandbox Code Playgroud)

这是一个方面.unnest()总是每行产生一个基本元素.我不确定你究竟想要什么结果.你的例子只是另一个2维数组,缺少一组大括号......?

{1,2,3}, {4,5,6}, {7,8,9}
Run Code Online (Sandbox Code Playgroud)

如果你想要一个数组,试试这个表示法:

SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[1:2]
Run Code Online (Sandbox Code Playgroud)

结果:

{{1,2,3},{4,5,6}}
Run Code Online (Sandbox Code Playgroud)

或这个:

SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[2:2][1:2]
Run Code Online (Sandbox Code Playgroud)

结果:

{{4,5}}
Run Code Online (Sandbox Code Playgroud)

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

请阅读手册中的更多内容.

功能

后来测试发现这个plpgsql函数快得多.需要Postgres 9.1或更高版本:

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;
Run Code Online (Sandbox Code Playgroud)

看到:

这是Lukas发布的功能的改进和简化版本:

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;
Run Code Online (Sandbox Code Playgroud)

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

CREATE AGGREGATE array_agg(anyelement) (
 SFUNC=array_append,
 STYPE=anyarray,
 INITCOND='{}'
);
Run Code Online (Sandbox Code Playgroud)

而且,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
...
Run Code Online (Sandbox Code Playgroud)

呼叫:

SELECT unnest_2d_1d(ARRAY[[1,2], [3,4], [5,6]]);
Run Code Online (Sandbox Code Playgroud)

结果

{1,2}
{3,4}
{5,6}
Run Code Online (Sandbox Code Playgroud)

SQL小提琴.


Luk*_*und 9

多维切片作为多维数组返回.这是unfst的修改版本,它将采用二维数组并返回一组1维数组.

update:已修改为使用内置的array_agg聚合函数,该函数默认为8.4.(http://www.postgresql.org/docs/9.2/static/functions-aggregate.html)

注意事项:

  • 它只适用于二维数组(我应该重命名该函数以反映该限制).
  • 如果您使用的是8.3(并且无法升级),则需要定义array_accum聚合,并将以下函数中的所有引用从array_agg更改为array_accum.http://www.postgresql.org/docs/8.3/static/xaggr.html

码:

CREATE OR REPLACE FUNCTION unnest_multidim(anyarray)
RETURNS SETOF anyarray AS
$BODY$
  SELECT array_agg($1[series2.i][series2.x]) FROM
    (SELECT generate_series(array_lower($1,2),array_upper($1,2)) as x, series1.i
     FROM 
     (SELECT generate_series(array_lower($1,1),array_upper($1,1)) as i) series1 
    ) series2
GROUP BY series2.i
$BODY$
LANGUAGE sql IMMUTABLE;
Run Code Online (Sandbox Code Playgroud)

结果:

select unnest_multidim(array[[1,2,3],[4,5,6],[7,8,9]]);
unnest_multidim
----------------------
{1,2,3}
{4,5,6}
{7,8,9}
(3 rows)
Run Code Online (Sandbox Code Playgroud)

现在,让我们说出于某种原因,您希望轻松访问返回的其中一个数组.以下函数添加一个可选的索引参数,该参数将返回您提供的索引的嵌套数组,或者,如果您提供null,则将输出完整的"unnested"数组.

CREATE OR REPLACE FUNCTION unnest_multidim(anyarray, integer)
  RETURNS SETOF anyarray AS
$BODY$
SELECT array_agg($1[series2.i][series2.x]) FROM
  (SELECT generate_series(array_lower($1,2),array_upper($1,2)) as x, series1.i
  FROM 
    (SELECT CASE WHEN $2  IS NULL THEN
      generate_series(array_lower($1,1),array_upper($1,1)) 
      ELSE $2
      END as i) series1
  ) series2
GROUP BY series2.i
$BODY$
LANGUAGE sql IMMUTABLE;
Run Code Online (Sandbox Code Playgroud)

结果:

db=> select unnest_multidim(array[[1,2,3],[4,5,6],[7,8,9]],2);
 unnest_multidim 
-----------------
 {4,5,6}
(1 row)

db=> select unnest_multidim(array[[1,2,3],[4,5,6],[7,8,9]],NULL);
 unnest_multidim 
-----------------
 {1,2,3}
 {4,5,6}
 {7,8,9}
(3 rows)
Run Code Online (Sandbox Code Playgroud)