Dau*_*aud 77 sql postgresql postgresql-9.1 postgresql-8.4
如果我array_agg用来收集名字,我会用逗号分隔我的名字,但是如果有一个null值,那么该null也被作为聚合中的名字.例如 :
SELECT g.id,
array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END) canonical_users,
array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END) non_canonical_users
FROM groups g
GROUP BY g.id;
Run Code Online (Sandbox Code Playgroud)
它返回,Larry,Phil而不是仅仅Larry,Phil(在我的9.1.2中,它显示NULL,Larry,Phil).就像在这个小提琴
相反,如果我使用string_agg()它,它只向我显示这里的名称(没有空逗号或空值)
问题是我已经Postgres 8.4安装在服务器上,并且string_agg()在那里不起作用.有没有办法使array_agg的工作类似于string_agg()?
Dal*_*ien 204
使用postgresql-9.3可以做到这一点;
SELECT g.id,
array_remove(array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END), NULL) canonical_users,
array_remove(array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END), NULL) non_canonical_users
FROM groups g
GROUP BY g.id;
Run Code Online (Sandbox Code Playgroud)
更新:使用postgresql-9.4;
SELECT g.id,
array_agg(g.users) FILTER (WHERE g.canonical = 'Y') canonical_users,
array_agg(g.users) FILTER (WHERE g.canonical = 'N') non_canonical_users
FROM groups g
GROUP BY g.id;
Run Code Online (Sandbox Code Playgroud)
Ale*_*ore 29
如果您正在寻找有关如何从数组中删除 NULL 的一般问题的现代答案,它是:
array_remove(your_array, NULL)
Run Code Online (Sandbox Code Playgroud)
我对性能特别好奇,并想将其与最佳替代方案进行比较:
CREATE OR REPLACE FUNCTION strip_nulls(
IN array_in ANYARRAY
)
RETURNS anyarray AS
'
SELECT
array_agg(a)
FROM unnest(array_in) a
WHERE
a IS NOT NULL
;
'
LANGUAGE sql
;
Run Code Online (Sandbox Code Playgroud)
进行 pgbench 测试证明(以高可信度)array_remove() 的速度快了两倍多一点。我对具有各种数组大小(10、100 和 1000 个元素)和介于两者之间的随机 NULL 的双精度数字进行了测试。
还值得注意的是,这可用于删除空格 ('' != NULL)。但是第二个参数接受anyelement,并且由于它们很可能是您用字符串文字表示空白,因此请确保将其转换为您想要的形式,通常是非数组。
例如:
select array_remove(array['abc', ''], ''::text);
如果你试试:
select array_remove(array['abc', ''], '');
它将假设 '' 是 TEXT[] (array) 并且会抛出这个错误:
错误:格式错误的数组文字:“”
Clo*_*eto 23
select
id,
(select array_agg(a) from unnest(canonical_users) a where a is not null) canonical_users,
(select array_agg(a) from unnest(non_canonical_users) a where a is not null) non_canonical_users
from (
SELECT g.id,
array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END) canonical_users,
array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END) non_canonical_users
FROM groups g
GROUP BY g.id
) s
Run Code Online (Sandbox Code Playgroud)
或者,更简单,可能更便宜,使用array_to_string它消除空值:
SELECT
g.id,
array_to_string(
array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END)
, ','
) canonical_users,
array_to_string(
array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END)
, ','
) non_canonical_users
FROM groups g
GROUP BY g.id
Run Code Online (Sandbox Code Playgroud)
ror*_*ycl 12
在解决从数组聚合中删除空值的一般问题时,有两种主要方法可以解决问题:执行array_agg(unnest(array_agg(x))或创建自定义聚合.
第一种是上面显示的形式:
SELECT
array_agg(u)
FROM (
SELECT
unnest(
array_agg(v)
) as u
FROM
x
) un
WHERE
u IS NOT NULL;
Run Code Online (Sandbox Code Playgroud)
第二:
/*
With reference to
http://ejrh.wordpress.com/2011/09/27/denormalisation-aggregate-function-for-postgresql/
*/
CREATE OR REPLACE FUNCTION fn_array_agg_notnull (
a anyarray
, b anyelement
) RETURNS ANYARRAY
AS $$
BEGIN
IF b IS NOT NULL THEN
a := array_append(a, b);
END IF;
RETURN a;
END;
$$ IMMUTABLE LANGUAGE 'plpgsql';
CREATE AGGREGATE array_agg_notnull(ANYELEMENT) (
SFUNC = fn_array_agg_notnull,
STYPE = ANYARRAY,
INITCOND = '{}'
);
Run Code Online (Sandbox Code Playgroud)
调用第二个(自然)看起来比第一个好一点:
从x中选择array_agg_notnull(v);
我正在添加这个,即使这个线程很老,但我遇到了这个在小数组上运行良好的巧妙技巧.它运行在Postgres 8.4+上,没有额外的库或功能.
string_to_array(array_to_string(array_agg(my_column)))::int[]
Run Code Online (Sandbox Code Playgroud)
该array_to_string()方法实际上摆脱了空值.
您应该array_agg用array_remove包装您的。
SELECT g.id,
array_remove(array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END), NULL) canonical_users,
array_remove(array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END), NULL) non_canonical_users
FROM groups g
GROUP BY g.id;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
49587 次 |
| 最近记录: |