PostgreSQL utilisant count () pour déterminer les pourcentages (problèmes de distribution)


19

J'essaie d'exécuter la requête suivante pour fournir le% de lignes de ma patientstable qui ont une valeur dans la refinstcolonne. J'obtiens toujours un résultat de 0.

select (count (refinst) / (select count(*) from patients) * 100) as "Formula" 
from patients;

Le tableau comporte 15556 lignes et select count(refinst) from patientsm'indique que 1446 d'entre elles ont une valeur dans la refinstcolonne. La réponse que j'aimerais obtenir de la requête serait 30,62 ( 1446/15556*100=30.62XXXXX, arrondie à deux décimales).

Je suis presque sûr que cela a quelque chose à voir avec le type de données des résultats de comptage (entiers, je suppose). Si je divise un entier par un entier et que le résultat est inférieur à 0, il est tronqué à 0 correct? Si tel est le cas, quelqu'un peut-il me montrer comment convertir les résultats des décomptes en nombre avec 2 décimales afin que le résultat soit également arrondi à 2 décimales?

Je suis sûr qu'il existe une meilleure façon d'écrire ce code que plusieurs instructions de comptage. Je recherche un moyen plus efficace pour écrire cette requête en particulier.


Peut-être que cette réponse peut vous aider.
Jhon Anderson Cardenas Diaz

Réponses:


26
SELECT (count(refinst) * 100)::numeric / count(*) AS refinst_percentage
FROM   patients;
  • N'utilisez pas de sous -sélection. Les deux agrégats peuvent être dérivés de la même requête. Moins cher.

  • En outre, ce n'est pas le cas pour les fonctions de fenêtre, car vous souhaitez calculer un seul résultat, et non un résultat par ligne.

  • Cast à n'importe quel type numérique qui prend en charge les chiffres fractionnaires, comme @a_horse déjà expliqué .
    Étant donné que vous voulez round()deux chiffres fractionnaires, je suggère numeric(ce qui est le même que decimaldans Postgres).
    Mais il suffit de lancer une valeur impliquée dans un calcul, de préférence la première. Postgres se contente automatiquement du type qui ne perd pas d'informations.

  • C'est généralement une bonne idée de multiplier avant de diviser . Cela minimise généralement les erreurs d'arrondi et est moins cher.
    Dans ce cas, la première multiplication ( count(refinst) * 100) peut être calculée avec une integerarithmétique exacte et bon marché . Ce n'est qu'alors que nous lançons numericet divisons par le suivant integer(que nous ne lançons pas en plus).

Arrondi à deux chiffres fractionnaires:

SELECT round((count(refinst) * 100)::numeric / count(*), 2) AS refinst_percentage
FROM   patients;

Bien sûr, vous avez raison, la fonction de fenêtre n'est pas nécessaire. Mais cela ne fait pas vraiment de différence (à part la lisibilité).
a_horse_with_no_name

3

Vous devez convertir chaque nombre impliqué dans la division en un type prenant en charge les décimales:

select (count(refinst)::decimal / (select count(*) from patients)::decimal) * 100  as "Formula" 
from patients;

Vous pouvez également essayer une fonction de fenêtre au lieu de la sous-requête scalaire. Cela pourrait être plus rapide:

select (count(refinst)::decimal / (count(*) over ())::decimal) * 100 as "Formula" 
from patients;

0

Je me rends compte que ce fil a quelques années mais: essayez de multiplier par 100,0 plutôt que par 100 Cela devrait automatiquement convertir le résultat en un flottant plutôt qu'en un entier.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.