1.3.4.8 行数

在使用 MySQL 时,经常会使碰到,查看某一种类型的数据有多少行?比方我们的例子中,想知道每个 owner 各有多少只宠物?计算多少只宠物和计算表中有多少行数据,其实是一个概念。下面我们使用 COUNT(*) 来实现。

检索拥有宠物的总量

mysql> SELECT COUNT(*) FROM pet;
+----------+
| COUNT(*) |
+----------+
|        9 |
+----------+
1 row in set (0.00 sec)

检索每个 owner 各有多少只宠物

mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;
+--------+----------+
| owner  | COUNT(*) |
+--------+----------+
| Benny  |        2 |
| Diane  |        2 |
| Gwen   |        3 |
| Harold |        2 |
+--------+----------+
4 rows in set (0.00 sec)

检索每个 species 各有多少只宠物

mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;
+---------+----------+
| species | COUNT(*) |
+---------+----------+
| bird    |        2 |
| cat     |        2 |
| dog     |        3 |
| hamster |        1 |
| snake   |        1 |
+---------+----------+
5 rows in set (0.00 sec)

检索每个 sex 各有多少只宠物

mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;
+------+----------+
| sex  | COUNT(*) |
+------+----------+
| NULL |        1 |
| f    |        4 |
| m    |        4 |
+------+----------+
3 rows in set (0.00 sec)

NULL 表示未知 sex

检索每个species、sex 各有多少只宠物

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 |
+---------+------+----------+
8 rows in set (0.00 sec)

上面的例子中,您仅想要 speciescat 、dog 的数据

mysql> SELECT species, sex, count(*) 
    -> FROM pet
    -> WHERE species = 'cat' or species = 'dog'
    -> GROUP BY species,sex;
+---------+------+----------+
| species | sex  | count(*) |
+---------+------+----------+
| cat     | f    |        1 |
| cat     | m    |        1 |
| dog     | f    |        1 |
| dog     | m    |        2 |
+---------+------+----------+
4 rows in set (0.00 sec)

如果您想过滤掉 sexNULL 的数据

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 |
+---------+------+----------+
7 rows in set (0.00 sec)

关于 ONLY_FULL_GROUP_BY

ONLY_FULL_GROUP_BYMySQL 提供的一个 sql_mode,通过这个sql_mode来提供SQL语句 GROUP BY 合法性的检查,在MySQL的sql_mode是非 ONLY_FULL_GROUP_BY 语义时。一条SELECT语句,MySQL允许target list中输出的表达式是除聚集函数或group by column以外的表达式 。

而对于语义限制都比较严谨的多家数据库,如SQLServer、Oracle、PostgreSql都不支持select target list中出现语义不明确的列,这样的语句在这些数据库中是会被报错的,所以从MySQL 5.7版本开始修正了这个语义,就是我们所说的 ONLY_FULL_GROUP_BY 语义,例如查看MySQL 5.7默认的sql_mode如下:

mysql> select @@sql_mode;
+-------------------------------------------------------------------------------+
| @@sql_mode                                                                    |
+------------------------------------------------------------------------------ +
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,
  ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION         |
+-------------------------------------------------------------------------------+
1 row in set (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='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,
NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; 
Query OK, 0 rows affected (0.00 sec)

再次执行查询

mysql> SELECT owner, COUNT(*) FROM pet;
+--------+----------+
| owner  | COUNT(*) |
+--------+----------+
| Harold |        9 |
+--------+----------+
1 row in set (0.00 sec)

关于 ONLY_FULL_GROUP_BY 后续的章节将详细介绍。

results matching ""

    No results matching ""