5.3.4.8 统计行数

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

计算您拥有的动物总数与“pet 表中有多少行?相同,因为每只宠物有一条记录。COUNT(*) 统计行数,因此计算动物数量的查询如下所示

Press CTRL+C to copy
mysql> SELECT COUNT(*) FROM pet; +----------+ | COUNT(*) | +----------+ | 9 | +----------+

之前,您检索了拥有宠物的人的姓名。如果您想了解每个主人有多少只宠物,可以使用 COUNT()

Press CTRL+C to copy
mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner; +--------+----------+ | owner | COUNT(*) | +--------+----------+ | Benny | 2 | | Diane | 2 | | Gwen | 3 | | Harold | 2 | +--------+----------+

前面的查询使用 GROUP BY 对每个 owner 的所有记录进行分组。将 COUNT()GROUP BY 结合使用对于在各种分组下表征数据非常有用。以下示例显示了执行动物普查操作的不同方法。

每个物种的动物数量

Press CTRL+C to copy
mysql> SELECT species, COUNT(*) FROM pet GROUP BY species; +---------+----------+ | species | COUNT(*) | +---------+----------+ | bird | 2 | | cat | 2 | | dog | 3 | | hamster | 1 | | snake | 1 | +---------+----------+

每种性别的动物数量

Press CTRL+C to copy
mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex; +------+----------+ | sex | COUNT(*) | +------+----------+ | NULL | 1 | | f | 4 | | m | 4 | +------+----------+

(在此输出中,NULL 表示性别未知。)

每个物种和性别组合的动物数量

Press CTRL+C to copy
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() 时,无需检索整个表。例如,之前的查询(仅对狗和猫执行)如下所示

Press CTRL+C to copy
mysql> SELECT species, sex, COUNT(*) FROM pet WHERE species = 'dog' OR species = 'cat' GROUP BY species, sex; +---------+------+----------+ | species | sex | COUNT(*) | +---------+------+----------+ | cat | f | 1 | | cat | m | 1 | | dog | f | 1 | | dog | m | 2 | +---------+------+----------+

或者,如果您只想了解已知性别的动物的每种性别的动物数量

Press CTRL+C to copy
mysql> SELECT species, sex, COUNT(*) FROM pet WHERE sex IS NOT NULL GROUP 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 模式,则会发生错误

    Press CTRL+C to copy
    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,则通过将所有行视为单个组来处理查询,但为每个命名列选择的值是不确定的。服务器可以自由选择任何行中的值

    Press CTRL+C to copy
    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)

另请参阅 第 14.19.3 节,“MySQL 对 GROUP BY 的处理”。有关 COUNT(expr) 行为和相关优化的信息,请参阅 第 14.19.1 节,“聚合函数说明”