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;
    $$;
但是,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]
返回相同
SELECT (ARRAY[[1,2,3], [4,5,6], [7,8,9]])[17]
默认情况下,数组维度的下限索引值设置为1.
0这里没有特别的意义.此外,对于二维数组,您需要两个索引来获取基本元素.像这样:
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()总是每行产生一个基本元素.我不确定你究竟想要什么结果.你的例子只是另一个2维数组,缺少一组大括号......?
{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}}
要展平结果(获取一维数组):
请阅读手册中的更多内容.
后来测试发现这个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;
看到:
这是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;
对于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}
多维切片作为多维数组返回.这是unfst的修改版本,它将采用二维数组并返回一组1维数组.
update:已修改为使用内置的array_agg聚合函数,该函数默认为8.4.(http://www.postgresql.org/docs/9.2/static/functions-aggregate.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;
结果:
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)
现在,让我们说出于某种原因,您希望轻松访问返回的其中一个数组.以下函数添加一个可选的索引参数,该参数将返回您提供的索引的嵌套数组,或者,如果您提供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;
结果:
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)