Pertama, masalah yang Anda hadapi di sini adalah apa yang Anda katakan adalah "Jika nilainya kurang dari 70, nilai dari ekspresi kasus ini adalah count(rank). Jika tidak, nilai dari ekspresi ini adalah count(rank) ." Jadi, dalam kedua kasus tersebut, Anda selalu mendapatkan nilai yang sama.
SELECT
CASE
WHEN grade < 70 THEN COUNT(rank)
ELSE COUNT(rank)
END
FROM
grades
count() hanya menghitung nilai non-null, jadi biasanya pola yang akan Anda lihat untuk mencapai apa yang Anda coba adalah ini:
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
Dengan cara itu ekspresi kasus hanya akan mengevaluasi ke 1 ketika ekspresi pengujian benar dan sebaliknya akan menjadi nol. Kemudian count() hanya akan menghitung instance non-null, yaitu ketika ekspresi pengujian benar, yang akan memberikan apa yang Anda butuhkan.
Sunting:Sebagai catatan tambahan, perhatikan bahwa ini persis sama dengan bagaimana Anda awalnya menulis ini menggunakan count(if(test, true-value, false-value))
, hanya ditulis ulang sebagai count(case when test then true-value end)
(dan null adalah nilai palsu karena else
tidak disertakan ke kasing).
Sunting:postgres 9.4 dirilis beberapa bulan setelah pertukaran asli ini. Versi tersebut memperkenalkan filter agregat, yang dapat membuat skenario seperti ini terlihat sedikit lebih bagus dan lebih jelas. Jawaban ini masih mendapat beberapa upvotes sesekali, jadi jika Anda menemukan di sini dan menggunakan postgres yang lebih baru (yaitu 9.4+), Anda mungkin ingin mempertimbangkan versi yang setara ini:
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