Този въпрос има повече, отколкото може да изглежда.
Опростена версия
Това е много по-бързо и по-лесно:
SELECT property_name
,(count(value_a = value_b OR NULL) * 100) / count(*) AS pct
FROM my_obj
GROUP BY 1;
Резултат:
property_name | pct
--------------+----
prop_1 | 17
prop_2 | 43
Как?
-
За това изобщо не се нуждаете от функция.
-
Вместо да броим
value_b(с което не е нужно да започвате) и за изчисляване на общата сума използвайтеcount(*)за общата сума. По-бързо, по-лесно. -
Това предполага, че нямате
NULLстойности. т.е. и двете колони са дефинираниNOT NULL. Във вашия въпрос липсва информация.
Ако не, първоначалната ви заявка вероятно не прави това, което смятате, че прави . Ако някоя от стойностите е NULL, вашата версия изобщо не отчита този ред. Можете дори да предизвикате деление на нула изключение по този начин.
Тази версия работи и с NULL.count(*)произвежда броя на всички редове, независимо от стойностите. -
Ето как работи броенето:
TRUE OR NULL = TRUE FALSE OR NULL = NULLcount()игнорира NULL стойности. Авоа. -
Приоритетът на оператора управлява това
=се свързва предиOR. Можете да добавите скоби, за да стане по-ясно:count ((value_a = value_b) OR FALSE) -
Можете да направите същото с
count NULLIF(<expression>, FALSE) -
Типът резултат на
count()еbigintпо подразбиране.
Делениеbigint / bigint, съкращава дробни цифри .
Включете дробни цифри
Използвайте 100.0 (с дробна цифра), за да принудите изчислението да бъде numeric и по този начин запазване на дробни цифри.
Може да искате да използвате round() с това:
SELECT property_name
,round((count(value_a = value_b OR NULL) * 100.0) / count(*), 2) AS pct
FROM my_obj
GROUP BY 1;
Резултат:
property_name | pct
--------------+-------
prop_1 | 17.23
prop_2 | 43.09
Като настрана:
използвам value_a вместо valueA . Не използвайте идентификатори със смесени главни букви без кавички в PostgreSQL. Виждал съм твърде много отчаяни въпроси, идващи от тази глупост. Ако се чудите за какво говоря, прочетете главата Идентификатори и ключови думи в ръководството.