避免在CASE表达式(PostgreSQL)中调用COUNT两次

避免在CASE表达式(PostgreSQL)中调用COUNT两次,sql,postgresql,Sql,Postgresql,在一个较大的查询中,我必须对一个变量进行计数,如果它大于1,则将计数作为字符串,否则为空字符串: CASE COUNT(measurement.id) > 1 THEN to_char(COUNT(measurement.id),' 999') ELSE '' 恐怕这太慢了,因为我使用了COUNT()两次。有更好的方法吗?此表达式: CASE COUNT(measurement.id) > 1 THEN to_char(COUNT(measurement.id),' 999') E

在一个较大的查询中,我必须对一个变量进行计数,如果它大于1,则将计数作为字符串,否则为空字符串:

CASE COUNT(measurement.id) > 1 THEN to_char(COUNT(measurement.id),' 999') ELSE ''
恐怕这太慢了,因为我使用了COUNT()两次。有更好的方法吗?

此表达式:

CASE COUNT(measurement.id) > 1 THEN to_char(COUNT(measurement.id),' 999') ELSE ''
不是很慢,因为调用了两次
COUNT()
。聚集数据的艰苦工作是将关键值聚集在一起的部分。单个聚合函数通常不是特别昂贵(也有例外,例如
COUNT(DISTINCT)
)。因此,即使它被多次调用,这也不是问题

您可以将查询更改为更神秘的内容,如:

coalesce(to_char(nullif(count(measurement.id), 0), '999')), '')
这将计数为0,将其转换为
NULL
,然后将其转换为空字符串(我认为它在Postgres中只对参数求值一次,尽管SQL Server会对其求值两次,在这种情况下,使用
isnull()
而不是
coalesce()
)。如果你觉得需要把漂亮的数字转换成字符串,我更喜欢你的版本

编辑:


COUNT()。我甚至不确定这是否正确,但事实就是如此。无论如何,它可能不会被调用两次,但最昂贵的部分是
GROUP BY

计数只会被评估一次。那太好了,是不是在文档中的某个地方?@RemcoGerlich。波动率()的定义中强烈暗示了这一点。我假设这适用于聚合函数,并且
COUNT()
被正确地声明为稳定的(为这篇小文章感到抱歉,我有点激动了…)聚合实际上没有声明的稳定性类。
pg_proc
中的条目只是一个占位符,用于保留函数签名,并防止在非聚合上下文中调用(请注意,
prosrc
只是一个占位符,因此
不可变的
可能是合适的)。稳定性类的整个概念不能(很容易)在这里应用,因为其明显的行为(将集合映射到标量值的函数)与实际情况(驱动一系列状态转换的一系列值)大不相同。大多数转换函数在技术上是不稳定的,尽管它们的声明是不稳定的,因为它们在累加器上执行就地更新。
COUNT()
函数有点违反分类,因为它实际上修改了它的输入……除此之外,聚合的行为就像它们是稳定的一样(即使它们不是):@NickBarnes…不是函数表现得像是稳定的。而是编译器将它们视为稳定的。你确定编译器没有为此使用元数据吗?对不起,这正是我想说的。如果计划者确实查看了稳定性标志,那么它似乎弄错了,因为
VOLATILE
函数调用是不稳定的ng在这方面进行了优化。它们也没有被视为不可变的:。在规划期间,将对该上下文中的不可变标量函数进行评估,并缓存以供后续调用
f()