postgresql - sql - “true”值的计数

发布于 2024-10-25 21:38:33 字数 349 浏览 1 评论 0原文

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

在上表中,如果我这样做:

select count(*), count(myCol);

我得到 6, 5

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

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

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

自由如风 2024-11-01 21:38:33
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>
SELECT COALESCE(sum(CASE WHEN myCol THEN 1 ELSE 0 END),0) FROM <table name>

or, as you found out for yourself:

SELECT count(CASE WHEN myCol THEN 1 END) FROM <table name>
放赐 2024-11-01 21:38:33

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

Since PostgreSQL 9.4 there's the FILTER clause, which allows for a very concise query to count the true values:

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

The above query is a bad example in that a simple WHERE clause would suffice, and is for demonstrating the syntax only. Where the FILTER clause shines is that it is easy to combine with other aggregates:

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

The clause is especially handy for aggregates on a column that uses another column as the predicate, while allowing to fetch differently filtered aggregates in a single query:

select count(*),
       sum(otherCol) filter (where myCol)
from tbl;
恰似旧人归 2024-11-01 21:38:33

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

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

你得到6,3

Cast the Boolean to an integer and sum.

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

You get 6,3.

我要还你自由 2024-11-01 21:38:33

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

probably, the best approach is to use nullif function.

in general

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

or in short

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

日裸衫吸 2024-11-01 21:38:33

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

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

The shortest and laziest (without casting) solution would be to use the formula:

SELECT COUNT(myCol OR NULL) FROM myTable;

Try it yourself:

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

gives the same result than

SELECT SUM(CASE WHEN x < 7 THEN 1 ELSE 0 END)
   FROM GENERATE_SERIES(0,10) t(x);
凶凌 2024-11-01 21:38:33

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

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

希望有帮助!

Simply convert boolean field to integer and do a sum. This will work on postgresql :

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

Hope that helps!

多彩岁月 2024-11-01 21:38:33
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 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

Or Maybe this

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;
我喜欢麦丽素 2024-11-01 21:38:33

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

In MySQL, you can do this as well:

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

I think that in Postgres, this works:

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

or better (to avoid :: and use standard SQL syntax):

SELECT count(*) AS total
     , sum(CAST(myCol AS int)) AS countTrue --convert Boolean to Integer
FROM yourTable
;
迷你仙 2024-11-01 21:38:33

基准

TL;DR:采用您喜欢的解决方案。没有显着差异。

实用程序脚本

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.4GHz 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

Benchmark

TL;DR: take the solution you like. There's no significant difference.

Utility scripts

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
}

Actual benchmark

Made on a 1.4GHz i5 MacBookPro, psql and pg 12.4 (pg in a linux docker container):

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
好倦 2024-11-01 21:38:33
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 count(*)         -- or count(myCol)
FROM   <table name>     -- replace <table name> with your table
WHERE  myCol = true;

Here's a way with Windowing Function:

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

-- Outputs:
-- --------------
-- myCol | count
-- ------+-------
--  f    |  2
--  t    |  3
--       |  1
蓝天 2024-11-01 21:38:33
select count(myCol)
from mytable
group by myCol
;

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

select count(myCol)
from mytable
group by myCol
;

will group the 3 possible states of bool (false, true, 0) in three rows
especially handy when grouping together with another column like day

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文