摘要:在本教程中,您将学习如何使用MySQL GROUP BY
根据列或表达式的值将行分组为子组。
MySQL GROUP BY 子句简介
GROUP BY
子句按列或表达式的值将一组行分组为一组汇总行。 GROUP BY
子句为每个组返回一行。换句话说,它减少了结果集中的行数。
GROUP BY
子句是SELECT
语句的可选子句。以下说明了GROUP BY
子句语法:
SELECT
c1, c2,..., cn, aggregate_function(ci)
FROM
table
WHERE
where_conditions
GROUP BY c1 , c2,...,cn;
Code language: SQL (Structured Query Language) (sql)
在此语法中,将GROUP BY
子句放置在FROM
和WHERE
子句之后。在 GROUP BY 关键字之后,放置一个以逗号分隔的列或表达式的列表,用于对行进行分组。
MySQL 在FROM
和WHERE
子句之后以及HAVING
、 SELECT
、 DISTINCT
、 ORDER BY
和LIMIT
子句之前评估GROUP BY
子句:
在实践中,您经常将GROUP BY
子句与聚合函数(例如SUM
、 AVG
、 MAX
、 MIN
和COUNT
一起使用。 SELECT
子句中出现的聚合函数提供每个组的信息。
MySQL GROUP BY 示例
让我们举一些使用GROUP BY
子句的示例。
A) 简单的 MySQL GROUP BY 示例
让我们看一下示例数据库中的orders
表。

假设您要将订单状态的值分组为子组,请使用带有status
列的GROUP BY
子句,如以下查询所示:
SELECT
status
FROM
orders
GROUP BY status;
Code language: SQL (Structured Query Language) (sql)

从输出中可以清楚地看到, GROUP BY
子句返回唯一出现的status
值。它的工作方式类似于DISTINCT
运算符,如以下查询所示:
SELECT DISTINCT
status
FROM
orders;
Code language: SQL (Structured Query Language) (sql)
B) 将 MySQL GROUP BY 与聚合函数结合使用
聚合函数允许您执行一组行的计算并返回单个值。 GROUP BY
子句通常与聚合函数一起使用来执行计算并为每个子组返回单个值。
例如,如果您想了解每种状态下的订单数量,可以使用带有GROUP BY
子句的COUNT
函数,如下所示:
SELECT
status, COUNT(*)
FROM
orders
GROUP BY status;
Code language: SQL (Structured Query Language) (sql)

请参阅下面的orders
和orderdetails
表。

要按状态获取所有订单的总金额,请将orders
表与orderdetails
表连接起来,并使用SUM
函数计算总金额。请参阅以下查询:
SELECT
status,
SUM(quantityOrdered * priceEach) AS amount
FROM
orders
INNER JOIN orderdetails
USING (orderNumber)
GROUP BY
status;
Code language: SQL (Structured Query Language) (sql)

同样,以下查询返回订单号和每个订单的总金额。
SELECT
orderNumber,
SUM(quantityOrdered * priceEach) AS total
FROM
orderdetails
GROUP BY
orderNumber;
Code language: SQL (Structured Query Language) (sql)

C) MySQL GROUP BY 和表达式示例
除了列之外,您还可以按表达式对行进行分组。以下查询获取每年的总销售额。
SELECT
YEAR(orderDate) AS year,
SUM(quantityOrdered * priceEach) AS total
FROM
orders
INNER JOIN orderdetails
USING (orderNumber)
WHERE
status = 'Shipped'
GROUP BY
YEAR(orderDate);
Code language: SQL (Structured Query Language) (sql)

在此示例中,我们使用YEAR
函数从订单日期 ( orderDate
) 中提取年份数据。我们仅将shipped
状态的订单纳入总销售额中。请注意, SELECT
子句中出现的表达式必须与GROUP BY
子句中出现的表达式相同。
D) 使用 MySQL GROUP BY 和 HAVING 子句示例
要过滤GROUP BY
子句返回的组,请使用HAVING
子句。以下查询使用HAVING
子句选择 2003 年之后年份的总销售额。
SELECT
YEAR(orderDate) AS year,
SUM(quantityOrdered * priceEach) AS total
FROM
orders
INNER JOIN orderdetails
USING (orderNumber)
WHERE
status = 'Shipped'
GROUP BY
year
HAVING
year > 2003;
Code language: SQL (Structured Query Language) (sql)

GROUP BY 子句:MySQL 与 SQL 标准
SQL 标准不允许您在GROUP BY
子句中使用别名,而 MySQL 支持这一点。
例如,以下查询从订单日期中提取年份。它首先使用year
作为表达式YEAR(orderDate)
的别名,然后在GROUP BY
子句中使用year
别名。
以下查询在 SQL 标准中无效:
SELECT
YEAR(orderDate) AS year,
COUNT(orderNumber)
FROM
orders
GROUP BY
year;
Code language: SQL (Structured Query Language) (sql)

此外,MySQL 允许您按升序或降序对组进行排序。默认排序顺序为升序。例如,如果要按状态获取订单数并按降序对状态进行排序,可以使用带有DESC
GROUP BY
子句,如下查询:
SELECT
status,
COUNT(*)
FROM
orders
GROUP BY
status DESC;
Code language: SQL (Structured Query Language) (sql)

请注意, GROUP BY
子句中的DESC
按降序对status
进行排序。您还可以在GROUP BY
子句中显式使用ASC
按状态升序对组进行排序。
GROUP BY 子句与 DISTINCT 子句
如果在SELECT
语句中使用GROUP BY
子句而不使用聚合函数,则GROUP BY
子句的行为类似于DISTINCT
子句。
以下语句使用GROUP BY
子句从customers
表中选择客户的唯一状态。
SELECT
state
FROM
customers
GROUP BY state;
Code language: SQL (Structured Query Language) (sql)

您可以使用DISTINCT
子句获得类似的结果:
SELECT DISTINCT
state
FROM
customers;
Code language: SQL (Structured Query Language) (sql)

一般来说, DISTINCT
子句是GROUP BY
子句的特例。 DISTINCT
子句和GROUP BY
子句之间的区别在于GROUP BY
子句对结果集进行排序,而DISTINCT
子句则不会。
请注意,MySQL 8.0 删除了GROUP BY
子句的隐式排序。因此,如果您使用MySQL 8.0+,您会发现上述带有GROUP BY
子句的查询的结果集没有排序。
如果在使用DISTINCT
子句的语句中添加ORDER BY
子句,则结果集会进行排序,并且与使用GROUP BY
子句的语句返回的结果集相同。
SELECT DISTINCT
state
FROM
customers
ORDER BY
state;
Code language: SQL (Structured Query Language) (sql)
概括
- 使用
GROUP BY
子句将行分组为子组。