MySQL GROUP BY

摘要:在本教程中,您将学习如何使用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子句放置在FROMWHERE子句之后。在 GROUP BY 关键字之后,放置一个以逗号分隔的列或表达式的列表,用于对行进行分组。

MySQL 在FROMWHERE子句之后以及HAVINGSELECTDISTINCTORDER BYLIMIT子句之前评估GROUP BY子句:

MySQL 分组依据

在实践中,您经常将GROUP BY子句与聚合函数(例如SUMAVGMAXMINCOUNT一起使用。 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)

试试看

MySQL GROUP BY 示例

从输出中可以清楚地看到, 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)

试试看

MySQL GROUP BY with COUNT function

请参阅下面的ordersorderdetails表。

订单订单详细信息表

要按状态获取所有订单的总金额,请将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)

试试看

MySQL GROUP BY 与 SUM 函数

同样,以下查询返回订单号和每个订单的总金额。

SELECT 
    orderNumber,
    SUM(quantityOrdered * priceEach) AS total
FROM
    orderdetails
GROUP BY 
    orderNumber;Code language: SQL (Structured Query Language) (sql)

试试看

MySQL GROUP BY 订单号示例

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)

试试看

MySQL GROUP BY 表达式示例

在此示例中,我们使用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)

试试看

MySQL GROUP BY 和 HAVING 示例

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 GROUP BY SQL 标准

此外,MySQL 允许您按升序或降序对组进行排序。默认排序顺序为升序。例如,如果要按状态获取订单数并按降序对状态进行排序,可以使用带有DESC GROUP BY子句,如下查询:

SELECT 
    status, 
    COUNT(*)
FROM
    orders
GROUP BY 
    status DESC;Code language: SQL (Structured Query Language) (sql)

试试看

MySQL GROUP BY DESC 示例

请注意, 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)

试试看

MySQL DISTINCT 与 GROUP BY 示例

您可以使用DISTINCT子句获得类似的结果:

SELECT DISTINCT
    state
FROM
    customers;Code language: SQL (Structured Query Language) (sql)

试试看

MySQL DISTINCT 与 GROUP BY 排序示例

一般来说, 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子句将行分组为子组。
本教程有帮助吗?