Using aggregate functions in a HAVING
clause is very much legal, since HAVING
eliminates group rows. Conditional counting can be achieved either by using the property that NULL
s don’t count:
count(expression)
… number of input rows for which the value of expression is not null
or if using PostgreSQL 9.4 or later, with the aggregate FILTER
clause:
count(*) FILTER (WHERE something > 0)
You could also use a sum of ones (and zeros).
PostgreSQL >= 9.4 and SQLAlchemy >= 1.0.0
Using a filtered aggregate function:
.having(func.count(1).filter(Question.accepted) >
func.count(1).filter(not_(Question.accepted)))
Older PostgreSQL and/or SQLAlchemy
The SQL analog for “if” is either CASE
expression or in this case nullif()
function. Both of them can be used together with the fact that NULL
s don’t count:
from sqlalchemy import case
...
.having(func.count(case([(Question.accepted, 1)])) >
func.count(case([(not_(Question.accepted), 1)])))
or:
.having(func.count(func.nullif(Question.accepted, False)) >
func.count(func.nullif(Question.accepted, True)))
Using nullif()
can be a bit confusing as the “condition” is what you don’t want to count. You could device an expression that would make the condition more natural, but that’s left for the reader. These 2 are more portable solutions, but on the other hand the FILTER
clause is standard, though not widely available.