postgresql-SQL-`true`值的计数


97
myCol
------
 true
 true
 true
 false
 false
 null

在上表中,如果这样做:

select count(*), count(myCol);

我懂了 6, 5

我得到,5因为它不计算空条目。

如何计算真实值的数量(示例中为3)?

(这是一种简化,实际上我在count函数中使用了一个复杂得多的表达式)

编辑摘要:我也想在查询中包含一个简单的count(*),所以不能使用where子句


't'代表True,'f'代表False吗?还是您正在寻找类似SELECT COUNT(DISTINCT myCol)之类的东西。
Shamit Verma 2011年

看一下我的第二个示例,WHERE myCol = true如果需要,可以在其中放一个,如果删除第一个,*,它将只返回数字。
vol7ron 2011年

@Shamit是,t代表真,f代表假,我更新了问题
EoghanM 2011年

您也可能不简化您的问题/查询...您的要求限制了更好的性能可能性,并且人们以低效的答案进行响应,而这些答案却无缘无故地遭到了抨击。
vol7ron 2011年

1
在我的辩护中,@ vol7ron必须进行一些简化才能提出一个易于理解的问题,但是是的,当我最初发布时,我过于简化了。
EoghanM 2011年

Answers:


133
SELECT COALESCE(sum(CASE WHEN myCol THEN 1 ELSE 0 END),0) FROM <table name>

或者,如您所知:

SELECT count(CASE WHEN myCol THEN 1 END) FROM <table name>

这是一个很好的技巧,可以从我这里得到正确的答案。除非有人提出更短的解决方案,否则我会接受的?
EoghanM 2011年

2
还有,您为什么使用sum(.. THEN 1 ELSE 0)而不是count(.. THEN true否则为null)的任何原因?
EoghanM 2011年

5
不...只是我不确定哪个值可以count()计数...而且我知道总和可以解决问题。但是请注意:第二个想法是,我相信只对null值使用sum()会返回null,因此对您来说应该为COALESCE(sum(...),0),换句话说,count()更好,
丹尼尔(Daniel)

1
@EoghanM,查看涉及演员表的简短答案。
Dwayne Towell 2014年

1
您实际上可以省略ELSE null以获得相同的结果。
200_success,2016年

91

将布尔值强制转换为整数和。

SELECT count(*),sum(myCol::int);

你得到6,3


3
Plus1:不错!这可能比我的解决方案还要快。
丹尼尔(Daniel)

1
这是最好,最短的解决方案(并且在许多其他编程环境和软件中具有等效功能)。应该更多投票

3
“从整数到计数”显然是最简洁的方法,但这并不是最好的方法。我不赞成这样做,因为尽管许多环境使用0/1表示假/真,但许多环境使用0 /非零,包括-1。我同意这是“骇客”,当演员不是“骇客”时,演员就足够了。不会投票,但不会再次认可。
安德鲁·沃尔夫 Andrew Wolfe)

81

从PostgreSQL 9.4开始,有FILTER子句,它允许非常简洁的查询来计算真实值:

select count(*) filter (where myCol)
from tbl;

上面的查询是一个不好的例子,因为一个简单的WHERE子句就足够了,并且仅用于说明语法。FILTER子句的亮点在于它很容易与其他聚合结合:

select count(*), -- all
       count(myCol), -- non null
       count(*) filter (where myCol) -- true
from tbl;

该子句对于使用另一个列作为谓词的列上的聚合特别方便,同时允许在单个查询中获取经过不同过滤的聚合:

select count(*),
       sum(otherCol) filter (where myCol)
from tbl;

2
对于PG> 9.4,这是最好的答案,而且速度非常快
Juan Ricardo

47

可能,最好的方法是使用nullif函数。

一般来说

select
    count(nullif(myCol = false, true)),  -- count true values
    count(nullif(myCol = true, true)),   -- count false values
    count(myCol);

或总之

select
    count(nullif(myCol, true)),  -- count false values
    count(nullif(myCol, false)), -- count true values
    count(myCol);

http://www.postgresql.org/docs/9.0/static/functions-conditional.html


2
您的“一般”看起来是错误的:AFAICS,如果[布尔表达式]为false,并且为true,nullif([boolean expression], true)则将返回,因此您将计算假值。我想你要。falsenullnullif([boolean expression], false)
rjmunro

是的,“一般”情况应该相反。固定。谢谢。
wrobell

1
育。该修复程序确实令人困惑。AFAICS,它现在将计算true或null值。我认为对它重新措辞以便您始终可以nullif([boolean expression], false)轻松阅读它。然后,您可以根据自己的喜好改变布尔表达式部分,在这种情况下,myCol = true可以计算真值,也myCol = false可以计算假值,或name='john'计算被称为john等的
人数。– rjmunro

19

最短和最懒惰(无强制转换)的解决方案是使用以下公式:

SELECT COUNT(myCol OR NULL) FROM myTable;

自己尝试:

SELECT COUNT(x < 7 OR NULL)
   FROM GENERATE_SERIES(0,10) t(x);

给出的结果与

SELECT SUM(CASE WHEN x < 7 THEN 1 ELSE 0 END)
   FROM GENERATE_SERIES(0,10) t(x);

这绝对比我的解决方案更好:)
Daniel

非常有见地的答案。
lucasarruda

7

在MySQL中,您也可以执行以下操作:

SELECT count(*) AS total
     , sum(myCol) AS countTrue --yes, you can add TRUEs as TRUE=1 and FALSE=0 !!
FROM yourTable
;

我认为这在Postgres中有效:

SELECT count(*) AS total
     , sum(myCol::int) AS countTrue --convert Boolean to Integer
FROM yourTable
;

或更好(避免::和使用标准SQL语法):

SELECT count(*) AS total
     , sum(CAST(myCol AS int)) AS countTrue --convert Boolean to Integer
FROM yourTable
;

这是我见过的最简单的解决方案^ _ ^
徐佳浩

7
select f1,
       CASE WHEN f1 = 't' THEN COUNT(*) 
            WHEN f1 = 'f' THEN COUNT(*) 
            END AS counts,
       (SELECT COUNT(*) FROM mytable) AS total_counts
from mytable
group by f1

也许这

SELECT SUM(CASE WHEN f1 = 't' THEN 1 END) AS t,
       SUM(CASE WHEN f1 = 'f' THEN 1 END) AS f,
       SUM(CASE WHEN f1 NOT IN ('t','f') OR f1 IS NULL THEN 1 END) AS others,
       SUM(CASE WHEN f1 IS NOT NULL OR f1 IS NULL THEN 1 ELSE 0 END) AS total_count
FROM mytable;

+1如果myColexpression是布尔值,则可以用where (myCol)
–ypercubeᵀᴹ

抱歉,我简化了我的示例:我不能使用where子句,因为我还想返回代表行总数的总计数以及真实值的计数。
EoghanM 2011年

7

只需将布尔字段转换为整数并求和即可。这将适用于postgresql:

select sum(myCol::int) from <table name>

希望有帮助!


它既不比其他解决方案更快也不更精确。我相信使用int作为布尔值对您来说更直观时,您来自Oracle。
丹尼尔

4
SELECT count(*)         -- or count(myCol)
FROM   <table name>     -- replace <table name> with your table
WHERE  myCol = true;

这是开窗功能的一种方式:

SELECT DISTINCT *, count(*) over(partition by myCol)
FROM   <table name>;

-- Outputs:
-- --------------
-- myCol | count
-- ------+-------
--  f    |  2
--  t    |  3
--       |  1

抱歉,对于我要应用此解决方案的更复杂的示例,我无法返回多行。
EoghanM 2011年

是的,但是您可以通过添加进一步限制它WHERE myCol = true。我提供第二个示例并不是因为它更快,而是更多关于Postgres窗口功能的教育性文章,许多用户对此感到不满意或不知道。
vol7ron 2011年

0
select count(myCol)
from mytable
group by myCol
;

会将bool的3种可能状态(false,true,0)分为三行,在与另一列(如day)一起分组时特别方便

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.