Извлечь процент от общего количества записей, имеющих конкретное значение в postgresql - PullRequest
0 голосов
/ 04 февраля 2020

В моей базе данных postgresql есть таблица людей. В этой таблице есть столбец 'sex', содержащий значения 'M' и 'F'. Я хотел бы получить процент этой таблицы, которая имеет пол «М».

Более конкретно, я хотел бы получить этот процент как часть группы по утверждению, которое группирует людей по почтовому индексу (у нас есть столбец почтового индекса) и возвращает процент мужчин каждого почтового индекса.

Этот оператор успешно выбирает количество мужчин во всей таблице.

select count(*) from contacts_6  and sex='M'

Этот оператор успешно выбирает общее количество людей в каждом почтовом индексе и группах по почтовому индексу ...

select home_zip,  count(*) as total from contacts_6 where home_zip != '' group by home_zip

Этот оператор успешно извлекает фиктивный процент, рассчитанный из фиктивного значения 2,0, деленного на общее число людей в каждом почтовом индексе и групп по почтовому индексу ...

select home_zip,  ROUND(2.0 / count(*), 3) as stat from contacts_6 where home_zip != '' group by home_zip

Как можно Я заменяю фиктивное значение 2.0 на фактическое число мужчин в почтовом индексе?

Я пробовал это ...

select home_zip,  ROUND((select b from 
                    (select count(*) from contacts_6 where contact_id < 10000 and sex='M') as b )
                    / count(*), 3) as stat from contacts_6 where home_zip != '' group by home_zip

, которое возвращает ошибку:

ОШИБКА: оператор не существует: record / bigint LINE 9: / count (*), 3) как stat из contacts_6, где home_zip ... ^ СОВЕТ: ни один оператор не соответствует заданному имени и типу аргумента. Возможно, вам придется добавить явные приведения типов. SQL состояние: 42883 символов: 695

Ответы [ 3 ]

1 голос
/ 04 февраля 2020

Вы можете выполнить условное агрегирование:

select 
    home_zip,  
    1.0 * round(sum( (sex = 'M')::int ) / count(*), 3) as stat 
from contacts_6 
where home_zip != '' 
group by home_zip

sum( (sex = 'M')::int ) подсчитывает, сколько записей в группе имеет sex = 'M'; это работает путем преобразования результата условия (true или false) в целочисленное значение (1 или 0) и суммирование значений.

Поскольку мы имеем дело с 0 / 1 значений, другой удобный способ сделать это - использовать avg():

select 
    home_zip,  
    round(avg( (sex = 'M')::int ), 3) as stat 
from contacts_6 
where home_zip != '' 
group by home_zip
0 голосов
/ 04 февраля 2020
select 
   sex, 
   round(count(*)*100/(select count(*) from contacts_6),2) AS Pucentage
from 
   contacts_6
group by  
   sex
having 
   sex = 'M'
0 голосов
/ 04 февраля 2020

Это, кажется, делает трюк. Есть ли лучший способ?

select home_zip,  ROUND(avg(case when sex = 'M' then 100.0 else 0.0 end), 3)
 as stat from contacts_6 where home_zip != ''  group by home_zip

Я нашел ответ в другом посте, закрыл страницу и не имею URl в моем кеше браузера.

...