postgresql - sql - count of `true` values

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

In the above table, if I do :

select count(*), count(myCol);

I get 6, 5

I get 5 as it doesn't count the null entry.

How do I also count the number of true values (3 in the example)?

(This is a simplification and I'm actually using a much more complicated expression within the count function)

Edit summary: I also want to include a plain count(*) in the query, so can't use a where clause

152736 次浏览
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;
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
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>

在 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
;

可能,最好的方法是使用 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

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

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

你得到 6,3

最短和最懒的解决方案(没有铸造)将使用的公式:

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);

因为 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;

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

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

希望能帮上忙!

select count(myCol)
from mytable
group by myCol
;

将 bool 的3种可能状态(false,true,0)分成三行 特别是当与另一列像白天一样分组时

基准

服用你喜欢的溶液,没有显著差异。

实用程序脚本

before(){
psql <<-SQL
create table bench (
id         serial
, thebool    boolean
);


insert into bench (thebool)
select (random() > 0.5)
from generate_series(1, 1e6) g;




analyze bench;
SQL
}
after(){
psql -c 'drop table bench'
}
test(){
echo $(tput bold)$1$(tput sgr0)
psql -c "explain analyze select $1 from bench" | tail -4 | head -2
}

实际基准

基于1.4 GHz i5 MacBookPro,psql 和 pg 12.4(pg 在 linux docker 容器中) :

before
test 'count(*) filter (where thebool)'
# Planning Time: 0.138 ms
# Execution Time: 4424.042 ms
test 'count(case when thebool then 1 end)'
# Planning Time: 0.156 ms
# Execution Time: 4638.861 ms
test 'count(nullif(thebool, false))'
# Planning Time: 0.201 ms
# Execution Time: 5267.631 ms
test 'count(thebool or null)'
# Planning Time: 0.202 ms
# Execution Time: 4672.700 ms
test 'sum(thebool::integer)'
# Planning Time: 0.155 ms
# Execution Time: 4602.406 ms
test 'coalesce(sum(case when thebool THEN 1 ELSE 0 END), 0)'
# Planning Time: 0.167 ms
# Execution Time: 4416.503 ms
after