我想获取一个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,我认为这是我问题的根源。
答案 0 :(得分:13)
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。我引用docs on that matter:
默认情况下,数组维度的下限索引值为 设置为一个。
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}}
展平结果(获取1D数组):
了解更多in the manual here。
后来的测试显示,这个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;
请参阅:
这是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()
。首先创建它:
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}
答案 1 :(得分:7)
多维切片作为多维数组返回。这是unfst的修改版本,它将采用二维数组并返回一组1维数组。
更新:已修改为使用内置的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)
答案 2 :(得分:0)
提醒一句:在postgres上使用array_agg&lt; 9命令可能会改变 PostgreSQL array_agg order 如果你打算使用unnested数组来查找argmax,这将破坏你的数据。