Ten eerste, het probleem dat je hier hebt, is dat wat je zegt is:"Als het cijfer lager is dan 70, is de waarde van deze hoofdletterexpressie count(rank). Anders is de waarde van deze expressie count(rank) ." In beide gevallen krijgt u dus altijd dezelfde waarde.
SELECT
CASE
WHEN grade < 70 THEN COUNT(rank)
ELSE COUNT(rank)
END
FROM
grades
count() telt alleen niet-null-waarden, dus het patroon dat u ziet om te bereiken wat u probeert, is meestal dit:
SELECT
count(CASE WHEN grade < 70 THEN 1 END) as grade_less_than_70,
count(CASE WHEN grade >= 70 and grade < 80 THEN 1 END) as grade_between_70_and_80
FROM
grades
Op die manier evalueert de case-expressie alleen naar 1 als de testexpressie waar is en is anders nul. Dan telt de count() alleen de niet-null-instanties, d.w.z. wanneer de testuitdrukking waar is, wat u zou moeten geven wat u nodig hebt.
Bewerken:merk op dat dit precies hetzelfde is als hoe je dit oorspronkelijk had geschreven met behulp van count(if(test, true-value, false-value))
, alleen herschreven als count(case when test then true-value end)
(en null is de stand in false-value sinds een else
niet bij de koffer geleverd).
Bewerken:postgres 9.4 werd een paar maanden na deze oorspronkelijke uitwisseling uitgebracht. Die versie introduceerde aggregaatfilters, waardoor scenario's als deze er een beetje mooier en duidelijker uit kunnen zien. Dit antwoord krijgt nog steeds af en toe upvotes, dus als je hier bent gestuit en een nieuwere postgres gebruikt (d.w.z. 9.4+), wil je misschien deze equivalente versie overwegen:
SELECT
count(*) filter (where grade < 70) as grade_less_than_70,
count(*) filter (where grade >= 70 and grade < 80) as grade_between_70_and_80
FROM
grades