SQL分组后是否默认统计行数?GROUP BY与COUNT()用法疑问
关于GROUP BY搭配COUNT(*)的逻辑解释
核心逻辑:GROUP BY分组后,COUNT(*)是实时计算每组的行数,SQL不会默认预存行数
当你执行SELECT type, COUNT(*) FROM exercise_logs GROUP BY type;时,SQL会先按type字段把所有行分成若干组(每个唯一的type值对应一个组,包括NULL值组如果存在的话),然后对每个组单独计算COUNT(*)——这个函数的作用就是统计当前组内包含的所有行数,不管行里的字段是否为NULL。
COUNT(*) vs COUNT(type)的区别
你提到的COUNT(type)和COUNT(*)是完全不同的:
COUNT(*):统计组内的总行数,哪怕某行的type字段是NULL,也会被算进去。COUNT(type):只统计组内type字段不为NULL的行数,如果某行的type是NULL,这行不会被计入这个统计值。
WHERE和COUNT的关系:WHERE是分组前过滤,不是用来搭配COUNT实现分组计数的
你之前误以为要用WHERE搭配COUNT(type),这是混淆了WHERE的作用:
WHERE是在分组之前筛选原始数据行,比如你只想统计type为“跑步”的记录数,直接写SELECT COUNT(*) FROM exercise_logs WHERE type = '跑步';即可(这里甚至不需要GROUP BY,因为只有一个组)。- 而如果是要按
type分组统计每组的行数,WHERE的作用是先过滤掉不需要的行再分组,比如SELECT type, COUNT(*) FROM exercise_logs WHERE type != '拉伸' GROUP BY type;——这是先排除所有type为“拉伸”的行,再对剩下的行按type分组计数。
实际例子参考
假设你的exercise_logs表有以下数据:
| id | type | duration |
|---|---|---|
| 1 | 跑步 | 30 |
| 2 | 跑步 | 25 |
| 3 | 游泳 | 40 |
| 4 | NULL | 15 |
| 5 | 游泳 | 35 |
执行SELECT type, COUNT(*) FROM exercise_logs GROUP BY type;的结果:
| type | COUNT(*) |
|---|---|
| 跑步 | 2 |
| 游泳 | 2 |
| NULL | 1 |
执行SELECT type, COUNT(type) FROM exercise_logs GROUP BY type;的结果:
| type | COUNT(type) |
|---|---|
| 跑步 | 2 |
| 游泳 | 2 |
| NULL | 0 |
加上WHERE过滤后的结果(SELECT type, COUNT(*) FROM exercise_logs WHERE type IS NOT NULL GROUP BY type;):
| type | COUNT(*) |
|---|---|
| 跑步 | 2 |
| 游泳 | 2 |
内容的提问来源于stack exchange,提问作者Krishan Sai
相关产品推荐
相关产品推荐

