如何轻松计算特定列为true
的行数和false
的数量?
我不能(或者我可以?)使用count()运行查询,因为我将此计数嵌入到having()子句中,如:
.having(func.count(Question.accepted) >
func.count(not_(Question.accepted)))
但是以上述方式,该函数计算不等式两边的每一行。
我试过这样的事情
.having(func.count(func.if_(Question.accepted, 1, 0)) >
func.count(func.if_(Question.accepted, 0, 1)))
但是我收到了错误
函数if(boolean,integer,integer)不存在
(似乎在postgresql中不存在)。
如何轻松计算列为true和false的行数?
答案 0 :(得分:3)
在HAVING
clause中使用聚合函数非常合法,因为HAVING
会消除组行。有条件的计数可以通过使用NULL
不计算的属性来实现:
count(expression)
...表达式的值不为空的输入行数
或使用PostgreSQL 9.4 or later时使用aggregate FILTER
clause:
count(*) FILTER (WHERE something > 0)
您还可以使用sum of ones (and zeros)。
使用filtered aggregate function:
.having(func.count(1).filter(Question.accepted) >
func.count(1).filter(not_(Question.accepted)))
&#34的SQL模拟;如果"是CASE
expression或本例nullif()
函数。它们都可以与NULL
不计数的事实一起使用:
from sqlalchemy import case
...
.having(func.count(case([(Question.accepted, 1)])) >
func.count(case([(not_(Question.accepted), 1)])))
或:
.having(func.count(func.nullif(Question.accepted, False)) >
func.count(func.nullif(Question.accepted, True)))
使用nullif()
可能有点令人困惑,因为"条件"是你 想要算什么的。您可以设置一个表达式,使条件更自然,但这是为读者留下的。这两个是更便携的解决方案,但另一方面,FILTER
条款是标准的,但没有广泛使用。
答案 1 :(得分:1)
您可以使用此查询:
Session.query(func.sum(case([(Question.accepted == True, 1)], else_=0).label('accepted_number'))
同一列将为False值,但条件为
时为False或者,您可以使用窗口功能:
Session.query(func.count(Question.id).over(partition_by=Question.accepted), Question.accepted).all()
结果将包含两行(如果Question.accepted中只有两个可能的值),其中第一列是值的数量,第二列是'accepted'列的值。
答案 2 :(得分:1)
大多数SQL风格都将布尔值存储为1位整数,并且对它们正确调用SUM可以为您提供正数布尔值/真行的数量。就您而言,您只需执行以下操作即可:
func.sum(Question.accepted)
如果您的SQL引擎返回布尔值的SUM作为布尔值(不确定是否有布尔值),则可以使用expression function cast()将其强制为整数,而不是使用func.count(case([(Question.accepted, 1)]))
:
func.sum(sqlalchemy.cast(Question.accepted, sqlalchemy.Integer))
最后,如果您希望Python端的总和为整数,expression function type_coerce()可以做到:
sqlalchemy.type_coerce(func.sum(Question.accepted), sqlalchemy.Integer)