Расчет процентов в Postgres - PullRequest
2 голосов
/ 29 мая 2019

Я совершенно новичок в PostgreSQL.У меня есть следующая таблица my_table:

a    b    c        date
1    0    good     2019-05-02
0    1    good     2019-05-02
1    1    bad      2019-05-02
1    1    good     2019-05-02
1    0    bad      2019-05-01
0    1    good     2019-05-01
1    1    bad      2019-05-01
0    0    bad      2019-05-01

Я хочу вычислить процент «хорошо» из столбца c для каждой даты.Я знаю, как получить число «хорошо»:

SELECT COUNT(c), date FROM my_table WHERE c != 'bad' GROUP BY date;

Что возвращает:

count    date
3        2019-05-02
1        2019-05-01

Моя цель состоит в том, чтобы получить это:

date         perc_good
2019-05-02   25
2019-05-01   75

ТакЯ попробовал следующее:

SELECT date, 
       (SELECT COUNT(c) 
        FROM my_table 
        WHERE c != 'bad' 
        GROUP BY date) / COUNT(c) * 100 as perc_good 
FROM my_table 
GROUP BY date;

И я получаю сообщение об ошибке, говорящее

более одной строки, возвращенной подзапросом, используемым в качестве выражения.

Я нашел этот ответ, но не уверен, как или если он применим к моему делу:

Расчет процента в PostgreSql

Как мне рассчитать процент для несколькихстроки?

Ответы [ 3 ]

2 голосов
/ 29 мая 2019

avg() удобно для этой цели:

select date,
       avg( (c = 'good')::int ) * 100 as percent_good
from t
group by date
order by date;

Как это работает?c = 'good' - логическое выражение.::int преобразует его в число, где 1 для true и 0 для false.Среднее тогда является средним для группы 1 и 0 и является отношением истинных значений.

1 голос
/ 29 мая 2019

Для этого случая вам нужно использовать условные AVG():

SELECT 
  date, 
  100 * avg(case when c = 'good' then 1 else 0 end) perc_good 
FROM my_table 
GROUP BY date;

См. Демоверсию .

1 голос
/ 29 мая 2019

Вы можете использовать условную сумму для получения хорошего значения и подсчета для общего количества

ниже примерного кода

  select  date
    , count(c) total 
    , sum(case when c='good' then 1 else 0 end)  total_good
    , sum(case when c='bad' then 1 else 0 end)  total_bad 
    , (sum(case when c='good' then 1 else 0 end) / count(c))* 100 perc_good
    , (sum(case when c='bad' then 1 else 0 end) / count(c))* 100 perc_bad 
  from my_table
  group by  date 

и за ваш результат

  select  date
    , (sum(case when c='good' then 1 else 0 end) / count(c))* 100 perc_good
  from my_table
  group by  date 

или как предложено a_horse_with_no_name с использованием фильтра count (*) ()

select  date
  , ((count(*) filter(where c='good'))/count(*))* 100 perc_good
from my_table
group by  date 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...