我正在使用聚合函数bool_or
并bool_and
聚合一些记录,并查看在特定列上是否存在分歧。根据官方文件:
bool_and(expression) true if all input values are true, otherwise false
bool_or(expression) true if at least one input value is true, otherwise false
但是这个测试查询:
SELECT bool_or(val),bool_and(val) FROM UNNEST(array[true,NULL]::bool[]) t(val)
true
两列的产量。
我认为bool_and
不包括NULL
价值观。有什么方法可以使用内置的聚合函数来返回上述查询true
和NULL
?
是的,NULL
这些聚合似乎忽略了输入。
这种愚蠢几乎可以肯定地直接来自于SQL标准(尽管我肯定不会花200美元来找出答案)。其他标准集合就像这样sum(var)
工作,似乎它们可能只是从那里推断出来的,而在处理null
值时没有考虑算术运算和布尔运算之间的固有差异。
我认为没有任何解决方法。我相信,可以说服这些函数返回a的唯一方法NULL
是为它们提供一个空数据集。(顺便说一句,谁坚持认为,sum()
零行应NULL
,而不是0
应该致力于...)
幸运的是,Postgres是无限可扩展的,定义自己的聚合很简单:
CREATE FUNCTION boolean_and(boolean, boolean) RETURNS boolean AS
'SELECT $1 AND $2'
LANGUAGE SQL IMMUTABLE;
CREATE AGGREGATE sensible_bool_and(boolean)
(
STYPE = boolean,
INITCOND = true,
SFUNC = boolean_and,
-- Optionally, to allow parallelisation:
COMBINEFUNC = boolean_and,
PARALLEL = SAFE
);
如果您只需要一次性查询,而又不想(或没有权限)向数据库添加新的聚合定义,则可以通过定义以下内容将它们放入本地连接的临时模式中并将它们称为pg_temp.boolean_and()
/ pg_temp.sensible_bool_and()
。
(如果使用的是连接池,则可能需要在完成后将其删除。)
请注意,这比内置速度慢约10倍bool_and()
(尽管在许多实际用例中这不太可能成为瓶颈);SQLboolean
值是堆分配的并且是不可变的,因此boolean_and()
需要为每次迭代分配一个新值,同时LANGUAGE C
允许函数就地更新累加器。如果性能是一个问题,并且您愿意/能够构建和部署自己的C模块,那么(与大多数内部函数一样),您可以轻松地复制粘贴bool_and()
实现并对其进行调整以满足您的需求。
但是,除非您确实有需要,否则所有这些都是矫kill过正。实际上,我可能会选择@Luke的解决方案。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句