数据库经常被用来回答这样的问题:“某种类型的数据在表中出现的频率是多少?”例如,你可能想知道你有多少只宠物,或者每个主人有多少只宠物,或者你可能想对你的动物进行各种类型的人口普查操作。
计算你拥有的动物总数与“pet表中有多少行?”这个问题是相同的,因为每个宠物都有一条记录。COUNT(*)用于计算行数,所以查询以计算你的动物的数量的SQL语句看起来是这样的:
mysql> SELECT COUNT(*) FROM pet;+----------+| COUNT(*) |+----------+| 9 |+----------+
早些时候,你检索了拥有宠物的人的名字。如果你想找出每个主人有多少宠物,你可以使用 COUNT() 函数。以下是一个使用 COUNT() 函数并结合 GROUP BY 来找出每个宠物主人拥有多少宠物的SQL查询示例:
mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;+--------+----------+| owner | COUNT(*) |+--------+----------+| Benny | 2 || Diane | 2 || Gwen | 3 || Harold | 2 |+--------+----------+前面的查询使用了
GROUP BY来按每个主人对所有记录进行分组。COUNT()与GROUP BY结合使用对于按不同分组来表征你的数据非常有用。以下示例展示了执行动物人口普查操作的不同方法。
每种物种的动物数量:
mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;+---------+----------+| species | COUNT(*) |+---------+----------+| bird | 2 || cat | 2 || dog | 3 || hamster | 1 || snake | 1 |+---------+----------+
按性别统计动物数量:
mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;+------+----------+| sex | COUNT(*) |+------+----------+| NULL | 1 || f | 4 || m | 4 |+------+----------+
(在这个输出中,NULL表示性别未知。)
按物种和性别的组合统计动物数量:
mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex;+---------+------+----------+| species | sex | COUNT(*) |+---------+------+----------+| bird | NULL | 1 || bird | f | 1 || cat | f | 1 || cat | m | 1 || dog | f | 1 || dog | m | 2 || hamster | f | 1 || snake | m | 1 |+---------+------+----------+
当你使用COUNT()时,你不需要检索整个表。例如,如果只对狗和猫执行前面的查询,查询将如下所示:
mysql> SELECT species, sex, COUNT(*) FROM petWHERE species = 'dog' OR species = 'cat'GROUP BY species, sex;+---------+------+----------+| species | sex | COUNT(*) |+---------+------+----------+| cat | f | 1 || cat | m | 1 || dog | f | 1 || dog | m | 2 |+---------+------+----------+
或者,如果你只想知道性别已知的动物的性别分布数量,可以这样查询:
mysql> SELECT species, sex, COUNT(*) FROM petWHERE sex IS NOT NULLGROUP BY species, sex;+---------+------+----------+| species | sex | COUNT(*) |+---------+------+----------+| bird | f | 1 || cat | f | 1 || cat | m | 1 || dog | f | 1 || dog | m | 2 || hamster | f | 1 || snake | m | 1 |+---------+------+----------+
如果你在COUNT()值之外还命名了要选择的列,那么应该存在一个GROUP BY子句,该子句命名了相同的列。否则,会发生以下情况:
如果启用了ONLY_FULL_GROUP_BY SQL模式,则会发生错误:
mysql> SET sql_mode = 'ONLY_FULL_GROUP_BY';Query OK, 0 rows affected (0.00 sec)mysql> SELECT owner, COUNT(*) FROM pet;ERROR 1140 (42000): In aggregated query without GROUP BY, expression#1 of SELECT list contains nonaggregated column 'menagerie.pet.owner';this is incompatible with sql_mode=only_full_group_by
如果ONLY_FULL_GROUP_BY没有启用,查询会将所有行视为一个单一组进行处理,但对于每个命名列所选的值是不确定的。服务器可以自由地从任何行中选择值:
mysql> SET sql_mode = '';Query OK, 0 rows affected (0.00 sec)mysql> SELECT owner, COUNT(*) FROM pet;+--------+----------+| owner | COUNT(*) |+--------+----------+| Harold | 8 |+--------+----------+1 row in set (0.00 sec)