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.