PostgreSQL中的array_agg错误:无法累积不同维数的数组

23
我在PostgreSQL中有一个包裹表,其中分区和分区说明列是array_agg转换为文本。新的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) zoning等方法,但这将返回一个完全混乱的列,其中包含嵌套的数组... 在此输入图像描述

根据此答案,这是我的更新查询,但它不起作用。

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
2个回答

35

示例数据:

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函数吗? - ziggy
2
我从未见过这种语法:< my_table, unnest(numbers) as number, unnest(letters) as letter > - ziggy
使用 t1 作为别名(alias),从 my_table 中选择 name、numbers 和 letters 列,其中 numbers 和 letters 列被展开成行。然后按照 name 分组,并对每个分组内的 numbers 和 letters 列进行去重后聚合成数组。 - ziggy
1
你的回答让我通过在FROM子句中使用unnest找到了解决方案。谢谢! - richddr
FROM子句对我也很重要。在Postgres 13中完美运行。 - leole
显示剩余6条评论

4

一个更简单的替代方法是创建一个自定义聚合函数(您只需要执行一次此操作)

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接