Как выбрать количество 0, 1, а также 0 и 1 в столбце таблицы postgres? - PullRequest
0 голосов
/ 23 марта 2020

Допустим, есть таблица, в которой есть столбцы с именами binary_value, name и created_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 -specifi c, и поэтому задаюсь вопросом, не является ли все это излишним.

Включая также 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 ]

1 голос
/ 23 марта 2020

Я думаю, вы просто хотите условную агрегацию:

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

Сравнение дат выглядит скорее, чем специфично c. Я предполагаю, что вы действительно задаете диапазон там.

Здесь - это SQL Fiddle.

Примечание: Если вы действительно используете Postgres 9.3, то вы не может использовать предложение filter (увы). Вместо этого:

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), () );
0 голосов
/ 23 марта 2020

Намного проще:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...