如何查询Room数据库:按Level分组统计done=1的记录数(含空值)
问题描述
我有一个名为Users的数据库表,结构及数据如下:
| Name | Level | Done |
|---|---|---|
| Allen | 1 | 0 |
| Diane | 1 | 0 |
| Victor | 2 | 1 |
| Gabriel | 3 | 0 |
| Roger | 4 | 0 |
| Julia | 4 | 1 |
我需要编写查询语句,按Level分组统计done=1的记录数,要求所有Level分组都显示,无符合条件的分组计数为0。
我已经实现了按Level分组统计所有记录数的查询:
SELECT Level, COUNT(*) FROM Users GROUP BY Level
结果符合预期:
1 -> 2 2 -> 1 3 -> 1 4 -> 2
但尝试以下查询时:
SELECT Level, COUNT(*) FROM Users WHERE done = 1 GROUP BY Level
得到结果:
2 -> 1 4 -> 1
无符合条件的分组被跳过,请求解决该问题。
解决方案
问题出在WHERE子句的执行时机——它会在分组之前过滤掉所有done≠1的行,导致那些没有符合条件记录的Level直接被排除在分组结果之外。
要保留所有Level分组并统计符合条件的记录数,需要使用条件计数,在分组时对符合条件的行单独计数,不符合的记为0。有两种常用写法:
方法1:使用COUNT()配合CASE表达式
SELECT Level, COUNT(CASE WHEN done = 1 THEN 1 END) AS done_count FROM Users GROUP BY Level ORDER BY Level;
原理
CASE WHEN done=1 THEN 1 END会对符合条件的行返回1,不符合的返回NULL;而COUNT()函数会忽略NULL值,最终统计的就是每个Level中done=1的记录数,没有符合条件的分组会返回0。
方法2:使用SUM()配合CASE表达式
SELECT Level, SUM(CASE WHEN done = 1 THEN 1 ELSE 0 END) AS done_count FROM Users GROUP BY Level ORDER BY Level;
原理
对符合条件的行返回1,不符合的返回0,用SUM()累加后得到的就是每个Level中done=1的记录数,无符合条件的分组自然返回0。
两种方法执行后的结果都为:
Level | done_count ------|----------- 1 | 0 2 | 1 3 | 0 4 | 1
内容的提问来源于stack exchange,提问作者Allison Grut
相关产品推荐
相关产品推荐

