För det första, problemet du har här är att det du säger är "Om betyget är mindre än 70 är värdet på detta kasusuttryck count(rank). Annars är värdet på detta uttryck count(rank) ." Så i båda fallen får du alltid samma värde.
SELECT
CASE
WHEN grade < 70 THEN COUNT(rank)
ELSE COUNT(rank)
END
FROM
grades
count() räknar bara icke-nullvärden, så vanligtvis är mönstret du ser för att uppnå det du försöker:
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
På så sätt kommer kasusuttrycket bara att utvärderas till 1 när testuttrycket är sant och kommer att vara null annars. Då kommer count() bara att räkna de icke-null-instanser, d.v.s. när testuttrycket är sant, vilket borde ge dig det du behöver.
Edit:Som en sidoanteckning, lägg märke till att detta är exakt samma som hur du ursprungligen skrev detta med count(if(test, true-value, false-value))
, endast omskriven som count(case when test then true-value end)
(och null är ställningen i falskt värde sedan en else
inte levererades till fallet).
Edit:postgres 9.4 släpptes några månader efter detta ursprungliga utbyte. Den versionen introducerade aggregerade filter, som kan få scenarier som detta att se lite snyggare och tydligare ut. Det här svaret får fortfarande enstaka uppröstningar, så om du har snubblat på här och använder en nyare postgres (dvs. 9.4+) kanske du vill överväga denna motsvarande version:
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