分组查询
我们要讨论的最后一个查询功能是 GROUP BY
子句。通过该子句,可以对同一表中具有共同字段的行进行分组。例如,假设我们想通过一次查询就知道每个作者有多少本书。试试下面的方法:
mysql> SELECT
-> author,
-> COUNT(*) AS amount,
-> GROUP_CONCAT(title SEPARATOR ', ') AS titles
-> FROM book
-> GROUP BY author
-> ORDER BY amount DESC, author;
+-----------------+--------+-------------------+
| author | amount | titles |
+-----------------+--------+-------------------+
| George Orwell | 2 | 1984, Animal Farm |
| Homer | 2 | Odyssey, Iliad |
| Bram Stoker | 1 | Dracula |
| Haruki Murakami | 1 | 1Q84 |
| J. M. Barrie | 1 | Peter Pan |
| Jodi Picoult | 1 | 19 minutes |
+-----------------+--------+-------------------+
5 rows in set (0.00 sec)
GROUP BY
子句总是在 WHERE
子句之后,它获取一个或多个字段(用逗号分隔),并将该字段具有相同值的所有记录视为一条记录。因此,按作者选择将分组所有包含相同作者的记录。这个功能看起来似乎不是很有用,但 MySQL 中有几个函数可以利用它。在这个例子中:
-
COUNT(*)
在使用 GROUP BY 的查询中使用,显示该字段分组的行数。在本例中,我们将用它来了解每位作者有多少本书。事实上,COUNT(*)
总是这样工作的;不过,对于不带GROUP BY
的查询,MySQL 会将整组记录视为一组。 -
GROUP_CONCAT
与我们前面讨论过的CONCAT
类似。唯一不同的是,这次函数将连接一个组中所有记录的字段。如果不指定SEPARATOR
,MySQL 将使用单个逗号。但是,在我们的例子中,我们需要一个逗号和一个空格来使其可读,所以我们在末尾添加了SEPARATOR ', '
。请注意,您可以在CONCAT
中添加任意多的连接内容,分隔符只是将连接内容按行分隔开来。
尽管这与分组无关,但请注意我们添加的 ORDER
子句。我们按两个字段而不是一个字段排序。这意味着,MySQL 将按 amount
字段对所有记录排序;注意,这是一个别名,但在这里也可以使用。然后,MySQL 将按照标题字段对具有相同 amount
值的每组记录进行排序。
我们已经介绍了 SELECT
查询可以包含的所有重要子句,因此还有最后一件事需要记住:MySQL 希望查询的子句始终保持相同的顺序。如果你写了同样的查询但改变了顺序,你将会得到一个错误。顺序如下:
-
SELECT
-
FROM
-
WHERE
-
GROUP BY
-
ORDER BY