9. 计算行

数据庫通常被用于回答问题,“在一个表中,特定的数据有多少条?”,例如,你可能想知道你有多少宠物,或者,每个宠物拥有者有多少只宠物,或者,在普查中,你可能想知道有多少种宠物。

计算你的宠物数量与“在你的宠物表中有多少行”是同样一个问题,因为每个宠物都有一个记录。COUNT(*)可以计算行的数量,所以,统计你宠物数量可以这样:

mysql> SELECT COUNT(*) FROM pet;
+----------+
| COUNT(*) |
+----------+
|        9 |
+----------+

早期,你查询人的名字,及此人所有宠物的数量,你会使用COUNT()来找到拥有者的宠物数量:

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()时,你不需要检索整个表。例如,对于前面的查询,当只查询dogs和cats时,可以像这样:

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 |
+---------+------+----------+

或者,如果你想知道,sex是已知的那些动物,每个性别所拥有的动物数量:

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模式是启用的,会发生这样的错误:

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)

See also Section 13.20.3, “MySQL Handling of GROUP BY”.