Je suis complètement nouveau dans PostgreSQL. J'ai le tableau suivant appelé my_table:
SELECT date, (SELECT COUNT(c) FROM my_table WHERE c != 'bad' GROUP BY date) / COUNT(c) * 100 as perc_good FROM my_table GROUP BY date;
Je veux calculer le pourcentage de «bon» de la colonne c pour chaque date. Je sais comment obtenir le nombre de "bons":
date perc_good 2019-05-02 25 2019-05-01 75
Cela renvoie:
count date 3 2019-05-02 1 2019-05-01
Mon objectif est d'obtenir ceci:
SELECT COUNT(c), date FROM my_table WHERE c != 'bad' GROUP BY date;
J'ai donc essayé ce qui suit:
a b c date 1 0 good 2019-05-02 0 1 good 2019-05-02 1 1 bad 2019-05-02 1 1 good 2019-05-02 1 0 bad 2019-05-01 0 1 good 2019-05-01 1 1 bad 2019-05-01 0 0 bad 2019-05-01
Et j'obtiens une erreur disant
plus d'une ligne renvoyée par une sous-requête utilisée comme expression.
J'ai trouvé cette réponse mais je ne sais pas comment ou si elle s'applique à mon cas:
Calcul du pourcentage dans PostgreSql
Comment calculer le pourcentage pour plusieurs lignes?
3 Réponses :
Vous pouvez utiliser une somme conditionnelle pour obtenir la bonne valeur et compter pour le total
sous un exemple de code explicatif
select date , ((count(*) filter(where c='good'))/count(*))* 100 perc_good from my_table group by date
et pour votre résultat
XXX
ou comme suggéré par a_horse_with_no_name en utilisant count (*) filter ()
select date , (sum(case when c='good' then 1 else 0 end) / count(c))* 100 perc_good from my_table group by date
Dans Postgres, vous pouvez simplifier les expressions CASE
par ex. filtre count (*) (où c = 'bon')
@a_horse_with_no_name .. correct. C'est mon habitude d'utiliser CASE
@Abelisto: qui utilise toujours la division entière, vous aurez besoin de (...) :: numeric / count (*)
pour éviter cela
@a_horse_with_no_name Oui sûrement. Mais en arithmétique entière x * 100 / y
généralement plus précis que x / y * 100
En fait, dans cette réponse, le résultat sera toujours 0
: < code> sélectionnez 99/100 * 100, 99 * 100/100;
avg ()
est pratique à cet effet:
select date, avg( (c = 'good')::int ) * 100 as percent_good from t group by date order by date;
Comment ça marche? c = 'good'
est une expression booléenne. Le :: int
le convertit en un nombre, avec 1 pour vrai et 0 pour faux. La moyenne est alors la moyenne d'un groupe de 1 et de 0 - et est le rapport des valeurs vraies.