布尔列上的SQLAlchemy func.count

时间:2016-05-19 16:13:06

标签: python postgresql sqlalchemy

如何轻松计算特定列为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的行数?

3 个答案:

答案 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)

PostgreSQL> = 9.4和SQLAlchemy> = 1.0.0

使用filtered aggregate function

.having(func.count(1).filter(Question.accepted) >
        func.count(1).filter(not_(Question.accepted)))

较旧的PostgreSQL和/或SQLAlchemy

&#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)