3.3.4.8 计算行数

数据库通常用于回答以下问题, “某一类型的数据在表中出现的频率是多少?” 例如, 你可能想知道你有多少宠物或者每个主人有多少宠物或者你可能对动物进行各种各样的普查.

计算你拥有的动物总数与“ pet 表中有多少条纪录?” 是同样的问题, 因为每只宠物只有一条纪录. COUNT(*) 计算行数, 因此你的动物数量的查询如下:

  1. mysql> SELECT COUNT(*) FROM pet;
  2. +----------+
  3. | COUNT(*) |
  4. +----------+
  5. | 9 |
  6. +----------+

之前, 你检索了拥有宠物的人的名字. 如果你想找出每个主人拥有多少宠物, 你可以使用 COUNT():

  1. mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;
  2. +--------+----------+
  3. | owner | COUNT(*) |
  4. +--------+----------+
  5. | Benny | 2 |
  6. | Diane | 2 |
  7. | Gwen | 3 |
  8. | Harold | 2 |
  9. +--------+----------+

前面的查询使用 GROUP BY 对每个 owner 的所有纪录进行分组. COUNT()GROUP BY 结合使用, 对描述不同分组下的数据非常有用. 下面的例子展示了执行动物普查的不同方法.

每种动物的数量:

  1. mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;
  2. +---------+----------+
  3. | species | COUNT(*) |
  4. +---------+----------+
  5. | bird | 2 |
  6. | cat | 2 |
  7. | dog | 3 |
  8. | hamster | 1 |
  9. | snake | 1 |
  10. +---------+----------+

每个性别的动物数量:

  1. mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;
  2. +------+----------+
  3. | sex | COUNT(*) |
  4. +------+----------+
  5. | NULL | 1 |
  6. | f | 4 |
  7. | m | 4 |
  8. +------+----------+

(在这个输出中, NULL 表示性别未知.)

按照动物的种类和性别组合计算数量:

  1. mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex;
  2. +---------+------+----------+
  3. | species | sex | COUNT(*) |
  4. +---------+------+----------+
  5. | bird | NULL | 1 |
  6. | bird | f | 1 |
  7. | cat | f | 1 |
  8. | cat | m | 1 |
  9. | dog | f | 1 |
  10. | dog | m | 2 |
  11. | hamster | f | 1 |
  12. | snake | m | 1 |
  13. +---------+------+----------+

你不需要使用COUNT() 时检索整个表. 例如, 在上一个查询, 仅对猫和狗进行查询, 如下所示:

  1. mysql> SELECT species, sex, COUNT(*) FROM pet
  2. WHERE species = 'dog' OR species = 'cat'
  3. GROUP BY species, sex;
  4. +---------+------+----------+
  5. | species | sex | COUNT(*) |
  6. +---------+------+----------+
  7. | cat | f | 1 |
  8. | cat | m | 1 |
  9. | dog | f | 1 |
  10. | dog | m | 2 |
  11. +---------+------+----------+

或者如果你想知道已知性别的动物每个性别的数量:

  1. mysql> SELECT species, sex, COUNT(*) FROM pet
  2. WHERE sex IS NOT NULL
  3. GROUP BY species, sex;
  4. +---------+------+----------+
  5. | species | sex | COUNT(*) |
  6. +---------+------+----------+
  7. | bird | f | 1 |
  8. | cat | f | 1 |
  9. | cat | m | 1 |
  10. | dog | f | 1 |
  11. | dog | m | 2 |
  12. | hamster | f | 1 |
  13. | snake | m | 1 |
  14. +---------+------+----------+

如果除了 COUNT() 值之外查询其他列, GROUP BY 子句应该用来命名为相同的列. 否则,会发生以下情况:

如果 ONLY_FULL_GROUP_BY SQL 模式启用了, 则会出现以下错误:

  1. mysql> SET sql_mode = 'ONLY_FULL_GROUP_BY';
  2. Query OK, 0 rows affected (0.00 sec)
  3. mysql> SELECT owner, COUNT(*) FROM pet;
  4. ERROR 1140 (42000): In aggregated query without GROUP BY, expression
  5. #1 of SELECT list contains nonaggregated column 'menagerie.pet.owner';
  6. this is incompatible with sql_mode=only_full_group_by

如果 ONLY_FULL_GROUP_BY 未启用, 查询会将所有的纪录当做单个组来处理t, 但是为每个指定的列选择的值是不确定的. 服务器可以从任意行中自由选择值:

  1. mysql> SET sql_mode = '';
  2. Query OK, 0 rows affected (0.00 sec)
  3. mysql> SELECT owner, COUNT(*) FROM pet;
  4. +--------+----------+
  5. | owner | COUNT(*) |
  6. +--------+----------+
  7. | Harold | 8 |
  8. +--------+----------+
  9. 1 row in set (0.00 sec)

参阅 Section 12.20.3, “MySQL GROUP BY 处理”. 参阅 Section 12.20.1, 聚合 (GROUP BY) 函数描述” 获取有关 COUNT(expr) 行为和相关优化的信息.