Há mais nesta pergunta do que parece.
Versão simples
Isso é muito mais rápido e simples:
SELECT property_name
,(count(value_a = value_b OR NULL) * 100) / count(*) AS pct
FROM my_obj
GROUP BY 1;
Resultado:
property_name | pct
--------------+----
prop_1 | 17
prop_2 | 43
Como?
-
Você não precisa de uma função para isso.
-
Em vez de contarvalue_b
(que você não precisa para começar) e calcular o total, usecount(*)
para o total. Mais rápido, mais simples.
-
Isso pressupõe que você não tenhaNULL
valores. Ou seja ambas as colunas são definidasNOT NULL
. As informações estão faltando na sua pergunta.
Caso contrário, sua consulta original provavelmente não está fazendo o que você acha que faz . Se algum dos valores for NULL, sua versão não contará essa linha. Você pode até provocar uma divisão por zero exceção desta forma.
Esta versão também funciona com NULL.count(*)
produz a contagem de todas as linhas, independentemente dos valores.
-
Veja como funciona a contagem:
TRUE OR NULL = TRUE FALSE OR NULL = NULL
count()
ignora valores NULL. Voilá.
-
A precedência do operador rege que=
vincula antes deOR
. Você pode adicionar parênteses para deixar mais claro:
count ((value_a = value_b) OR FALSE)
-
Você pode fazer o mesmo com
count NULLIF(<expression>, FALSE)
-
O tipo de resultado decount()
ébigint
por padrão.
Uma divisãobigint / bigint
, trunca dígitos fracionários .
Incluir dígitos fracionários
Use
100.0
(com dígito fracionário) para forçar o cálculo a ser numeric
e assim preservar dígitos fracionários.Você pode querer usar
round()
com isso:SELECT property_name
,round((count(value_a = value_b OR NULL) * 100.0) / count(*), 2) AS pct
FROM my_obj
GROUP BY 1;
Resultado:
property_name | pct
--------------+-------
prop_1 | 17.23
prop_2 | 43.09
Como um aparte:
eu uso
value_a
em vez de valueA
. Não use identificadores de maiúsculas e minúsculas sem aspas no PostgreSQL. Tenho visto muitas perguntas desesperadas provenientes dessa loucura. Se você quer saber do que estou falando, leia o capítulo Identificadores e Palavras-Chave do manual.