我有一个自定义的聚合求和函数,可以接受布尔类型的数据:
create or replace function badd (bigint, boolean)
returns bigint as
$body$
select $1 + case when $2 then 1 else 0 end;
$body$ language sql;
create aggregate sum(boolean) (
sfunc=badd,
stype=int8,
initcond='0'
);
这个聚合应该计算有多少行是TRUE
。例如,以下内容应该返回2(确实如此):
with t (x) as
(values
(true::boolean),
(false::boolean),
(true::boolean),
(null::boolean)
)
select sum(x) from t;
然而,它的性能相当糟糕,比使用整数转换慢了5.5倍:
with t as (select (gs > 0.5) as test_vector from generate_series(1,1000000,1) gs)
select sum(test_vector) from t; -- 52012ms
with t as (select (gs > 0.5) as test_vector from generate_series(1,1000000,1) gs)
select sum(test_vector::int) from t; -- 9484ms
想要改进这个聚合函数的唯一方法是编写一些新的 C 函数,例如在 src/backend/utils/adt/numeric.c
中的 int2_sum
函数的替代品吗?
$1 + $2 :: int
,或者$1 + case $2 when true then 1 else 0 end
,或类似的东西。 - Denis de Bernardyselect sum(x::int) from t;
和select sum(1) from t where x;
都是正确的且更快。 - foibs