Първо, проблемът, който имате тук, е, че това, което казвате, е „Ако оценката е по-малка от 70, стойността на този израз за случай е count(rank). В противен случай стойността на този израз е count(rank) " Така че и в двата случая винаги получавате една и съща стойност.
SELECT
CASE
WHEN grade < 70 THEN COUNT(rank)
ELSE COUNT(rank)
END
FROM
grades
count() отчита само ненулеви стойности, така че обикновено моделът, който ще видите, за да постигнете това, което се опитвате, е следният:
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
По този начин изразът case ще се оценява само на 1, когато тестовият израз е true и ще бъде нулев в противен случай. Тогава count() ще брои само ненулевите екземпляри, т.е. когато тестовият израз е вярно, което трябва да ви даде това, от което се нуждаете.
Редактиране:Като странична забележка, забележете, че това е точно същото като първоначално написано това с помощта на count(if(test, true-value, false-value))
, само пренаписано като count(case when test then true-value end)
(и null е стойката във false-value, тъй като else
не е предоставена в кутията).
Редактиране:postgres 9.4 беше пуснат няколко месеца след този оригинален обмен. Тази версия въведе обобщени филтри, които могат да направят сценарии като този да изглеждат малко по-хубави и по-ясни. Този отговор все още получава някои от време на време положителни гласове, така че ако сте попаднали тук и използвате по-нов postgres (т.е. 9.4+), може да искате да помислите за тази еквивалентна версия:
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