[英]How to select count of 0s, 1s, and both 0s and 1s in a postgres table column?
Say there's a table that has columns named binary_value
, name
, and created_at
along with the id
column.假设有一个表,其中包含名为
binary_value
、 name
和created_at
的列以及id
列。
Here's the SQL Fiddle for this question: http://sqlfiddle.com/#!15/d15d1/36这是这个问题的 SQL Fiddle: http ://sqlfiddle.com/#!15/d15d1/36
What would be an efficient query to get a result like the following?获得如下结果的有效查询是什么?
ones_count | zeros_count | total
3 | 1 | 4
So far, I've got:到目前为止,我有:
with cte2(count_type, counted) as (
with cte as (
select binary_value,
sum(case when binary_value = 1 then 1 else 0 end) as ones_count,
sum(case when binary_value = 0 then 1 else 0 end) as zeros_count
from infos
where name = 'me'
and created_at >= '2020-03-10 21:13:01.319677'
and created_at <= '2020-03-10 21:13:01.619677'
group by binary_value
)
select 'ones_count', ones_count from cte where binary_value = 1
union
select 'ones_count', zeros_count from cte where binary_value = 0
union
select 'total', sum(ones_count + zeros_count) as total from cte
)
select * from cte2;
Which gives it in column form:它以列形式给出:
count_type | counted
ones_count | 1
total | 4
ones_count | 3
How can we get the result in a row?我们怎样才能连续得到结果? Perhaps there's a different approach altogether than Common Table Expression?
也许有一种与 Common Table Expression 完全不同的方法? I'm starting to look at crosstab, which is postgres-specific, and so wondering if all this is overkill.
我开始研究交叉表,它是 postgres 特定的,所以想知道这一切是否太过分了。
Including DDL and data here, too:这里也包括 DDL 和数据:
create table infos (
id serial primary key,
name character varying not null,
binary_value integer not null,
created_at timestamp without time zone not null
)
insert into infos ("binary_value", "name", "created_at") values
(1, 'me', '2020-03-10 21:13:01.319677'),
(1, 'me', '2020-03-10 21:13:01.419677'),
(0, 'me', '2020-03-10 21:13:01.519677'),
(1, 'me', '2020-03-10 21:13:01.619677');
I think you just want conditional aggregation:我认为你只想要条件聚合:
select count(*) filter (where binary_value = 0) as num_0s,
count(*) filter (where binary_value = 1) as num_1s,
count(*)
from infos
where name = 'me' and
created_at >= '2020-03-10 21:13:01.319677' and
created_at <= '2020-03-10 21:13:01.619677';
The date comparison looks rather, uh, specific.日期比较看起来相当,呃,具体。 I assume that you really intend a range there.
我假设你真的打算在那里建立一个范围。
Here is a SQL Fiddle.这是一个 SQL 小提琴。
Note: If you are really using Postgres 9.3, then you can't use the filter
clause (alas).注意:如果你真的在使用 Postgres 9.3,那么你就不能使用
filter
子句(唉)。 Instead:反而:
select sum( (binary_value = 0)::int ) as num_0s,
sum( (binary_value = 1)::int ) as num_1s,
count(*)
from infos
where name = 'me' and
created_at >= '2020-03-10 21:13:01.319677' and
created_at <= '2020-03-10 21:13:01.619677';
Also, if you wanted the results in three separate rows, a simpler query is:此外,如果您希望结果在三个单独的行中,一个更简单的查询是:
select binary_value, count(*)
from infos
where name = 'me' and
created_at >= '2020-03-10 21:13:01.319677' and
created_at <= '2020-03-10 21:13:01.619677'
group by grouping sets ( (binary_value), () );
Much simpler:更简单:
select
sum(case when binary_value = 1 then 1 else 0 end) as ones_count,
sum(case when binary_value = 0 then 1 else 0 end) as zeroes_count,
count(*) as total
from infos
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.