如何在postgres表列中选择0、1和0和1的计数?

时间:2020-03-23 20:18:58

标签: sql postgresql

假设有一个表,其中包含名为binary_valuenamecreated_at的列以及id列。

以下是此问题的SQL小提琴:http://sqlfiddle.com/#!15/d15d1/36

要获得如下所示的结果,什么是有效的查询?

ones_count | zeros_count | total
3 | 1 | 4

到目前为止,我有:

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;

以列形式给出:

count_type | counted
ones_count | 1
total | 4
ones_count | 3

如何连续获取结果?也许有一种与通用表表达式完全不同的方法?我开始看一下交叉表,它是postgres特有的,所以想知道这是否太矫kill过正。

这里也包含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');

2 个答案:

答案 0 :(得分:1)

我认为您只需要条件聚合:

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

日期比较看起来很具体。我认为您确实打算在那儿设个范围。

Here是一个SQL提琴。

注意:如果您确实使用的是Postgres 9.3,则不能使用filter子句(alas)。相反:

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

此外,如果您希望将结果分成三行,则更简单的查询是:

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

答案 1 :(得分:0)

简单得多:

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