Det finns mer i denna fråga än vad det kan verka.
Enkel version
Det här är mycket snabbare och enklare:
SELECT property_name
,(count(value_a = value_b OR NULL) * 100) / count(*) AS pct
FROM my_obj
GROUP BY 1;
Resultat:
property_name | pct
--------------+----
prop_1 | 17
prop_2 | 43
Hur?
-
Du behöver ingen funktion för detta alls.
-
Istället för att räkna
value_b
(vilket du inte behöver till att börja med) och beräkna summan, användcount(*)
för det totala. Snabbare, enklare. -
Detta förutsätter att du inte har
NULL
värden. d.v.s. båda kolumnerna är definieradeNOT NULL
. Informationen saknas i din fråga.
Om inte gör din ursprungliga fråga förmodligen inte som du tror att den gör . Om något av värdena är NULL, räknar din version inte den raden alls. Du kan till och med provocera fram en division-för-noll undantag på detta sätt.
Denna version fungerar också med NULL.count(*)
producerar räkningen av alla rader, oavsett värden. -
Så här fungerar räkningen:
TRUE OR NULL = TRUE FALSE OR NULL = NULL
count()
ignorerar NULL-värden. Voilá. -
Operatörsföreträde styr den
=
binder föreOR
. Du kan lägga till parenteser för att göra det tydligare:count ((value_a = value_b) OR FALSE)
-
Du kan göra samma sak med
count NULLIF(<expression>, FALSE)
-
Resultattypen
count()
ärbigint
som standard.
En divisionbigint / bigint
, kortar av bråksiffror .
Inkludera bråksiffror
Använd 100.0
(med bråktal) för att tvinga beräkningen att vara numeric
och därigenom bevara bråksiffror.
Du kanske vill använda round()
med detta:
SELECT property_name
,round((count(value_a = value_b OR NULL) * 100.0) / count(*), 2) AS pct
FROM my_obj
GROUP BY 1;
Resultat:
property_name | pct
--------------+-------
prop_1 | 17.23
prop_2 | 43.09
Som en sida:
Jag använder value_a
istället för valueA
. Använd inte identifierare med blandade skiftlägen utan citat i PostgreSQL. Jag har sett för många desperata frågor komma från denna dårskap. Om du undrar vad jag pratar om, läs kapitlet Identifierare och nyckelord i manualen.