Този въпрос има повече, отколкото може да изглежда.
Опростена версия
Това е много по-бързо и по-лесно:
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 = NULL
count()
игнорира 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. Виждал съм твърде много отчаяни въпроси, идващи от тази глупост. Ако се чудите за какво говоря, прочетете главата Идентификатори и ключови думи в ръководството.