postgres array_agg 错误:无法累积不同维度的数组

Posted

技术标签:

【中文标题】postgres array_agg 错误:无法累积不同维度的数组【英文标题】:postgres array_agg ERROR: cannot accumulate arrays of different dimensionality 【发布时间】:2018-04-29 09:13:00 【问题描述】:

我在 postgresql 中有一个 parcels 表,其中 zoning 和 zoning_description 列被 array_agg 转换为文本。 new.universities 表有 9 行,我需要在输出中返回 9 行。

此查询的目的是找到这些大学所在的所有属性,并将分区类型折叠为 1 个唯一列,并将它们的几何图形合并/分解为多面体

select array_agg(distinct dp.zoning) zoning,array_agg(distinct dp.zoning_description) zoning_description,
    uni.school name_,uni.address,'University' type_,1000 buff,st_union(dp.geom) 
from new.universities uni join new.detroit_parcels_update dp
on st_intersects(st_buffer(uni.geom,-10),dp.geom)
group by name_,uni.address,type_,buff

我收到此错误

ERROR:  cannot accumulate arrays of different dimensionality
********** Error **********

ERROR: cannot accumulate arrays of different dimensionality
SQL state: 2202E

我可以做 array_agg(distinct dp.zoning::text) 分区等。但这会返回一个完全混乱的列,其中包含数组中的嵌套数组...

根据这里的答案是我更新的查询不起作用

select array_agg(distinct zoning_u) zoning,array_agg(distinct zoning_description_u) zoning_description,
        uni.school name_,uni.address,'University' type_,1000::int buff,st_union(dp.geom) geom
from new.detroit_parcels_update dp,unnest(zoning) zoning_u,
unnest(zoning_description) zoning_description_u
join new.universities uni
on st_intersects(st_buffer(uni.geom,-10),dp.geom)
group by name_,uni.address,type_,buff order by name_

得到这个错误

ERROR:  invalid reference to FROM-clause entry for table "dp"
LINE 6: on st_intersects(st_buffer(uni.geom,-10),dp.geom)
                                                 ^
HINT:  There is an entry for table "dp", but it cannot be referenced from this part of the query.

********** Error **********

ERROR: invalid reference to FROM-clause entry for table "dp"
SQL state: 42P01
Hint: There is an entry for table "dp", but it cannot be referenced from this part of the query.
Character: 373

我的最终查询是

with t as(select dp.zoning,dp.zoning_description,uni.school name_,uni.address,'University' type_,1000::int buff,st_union(dp.geom) geom
    from new.detroit_parcels_update dp
    join new.universities uni
    on st_intersects(st_buffer(uni.geom,-10),dp.geom)
    group by name_,uni.address,type_,buff,dp.zoning,zoning_description order by name_
    )
select name_,address,type_,buff,st_union(geom) geom,array_agg(distinct z) zoning, array_agg(distinct zd) zoning_description
from t,unnest(zoning) z,unnest(zoning_description) zd 
group by name_,address,type_,buff

【问题讨论】:

【参考方案1】:

示例数据:

create table my_table(name text, numbers text[], letters text[]);
insert into my_table values
    ('first',  '1, 2', 'a'   ),
    ('first',  '2, 3', 'a, b'),
    ('second', '4',    'c, d'),
    ('second', '5, 6', 'c'   );

您应该聚合数组元素,而不是数组。使用unnest():

select 
    name, 
    array_agg(distinct number) as numbers, 
    array_agg(distinct letter) as letters
from 
    my_table, 
    unnest(numbers) as number, 
    unnest(letters) as letter
group by name;

  name  | numbers | letters 
--------+---------+---------
 first  | 1,2,3 | a,b
 second | 4,5,6 | c,d
(2 rows)    

或者,您可以创建自定义聚合。您需要一个函数来合并数组(删除重复项的串联):

create or replace function public.array_merge(arr1 anyarray, arr2 anyarray)
    returns anyarray language sql immutable
as $$
    select array_agg(distinct elem order by elem)
    from (
        select unnest(arr1) elem 
        union
        select unnest(arr2)
    ) s
$$;

create aggregate array_merge_agg(anyarray) (
    sfunc = array_merge,
    stype = anyarray
);

select 
    name, 
    array_merge_agg(numbers) as numbers, 
    array_merge_agg(letters) as letters
from my_table
group by name;

【讨论】:

亲爱的,今晚晚些时候我将尝试您的第一个建议。 unnest 是一个标准的 postgres 函数吗? 是的,see it in the documentation. 我从未见过< my_table, unnest(numbers) as number, unnest(letters) as letter >的这种语法 这对我来说更有意义< with t1 as(select name,unnest(numbers) numbers,unnest(letters) letters from my_table) select name, array_agg(distinct numbers) as numbers, array_agg(distinct letters) as letters from t1 group by name > 您的回答通过在 FROM 子句中使用 unnest 引导我找到了我的解决方案。谢谢!【参考方案2】:

一个多simpler alternative是创建一个自定义聚合函数(你只需要这样做一次)

CREATE AGGREGATE array_concat_agg(anyarray) (
   SFUNC = array_cat,
   STYPE = anyarray
);

然后将array_agg 替换为array_concat_agg

SELECT
    array_concat_agg(DISTINCT dp.zoning) zoning,
    array_concat_agg(DISTINCT dp.zoning_description) zoning_description,
    uni.school name_,
    uni.address,
    'University' type_,
    1000 buff,
    st_union(dp.geom)
FROM
    new.universities uni
    JOIN new.detroit_parcels_update dp ON st_intersects(st_buffer(uni.geom, - 10), dp.geom)
GROUP BY
    name_,
    uni.address,
    type_,
    buff

【讨论】:

以上是关于postgres array_agg 错误:无法累积不同维度的数组的主要内容,如果未能解决你的问题,请参考以下文章

Postgres 未在 array_agg 查询中返回数据,如下所示

如何删除使用 array_agg postgres 函数生成的重复项

单个查询中的多个 array_agg() 调用

我如何联接两个以上的postgres表,并在postgres中将其作为nestedjson获得结果

PL/PGSQL - 无法将 SELECT 语句中的 array_agg 分配给变量

如何将现有函数(包括聚合)包装到 Postgres 中的新函数中?