Skip to content

sql-group-by

本章将解释 GROUP BY 子句(分组),这是一个用于汇总数据的基本 SQL 工具。您将学习如何将其与聚合函数结合使用以创建强大的汇总报告,按单个或多个列进行分组,并使用 HAVING 子句(分组过滤)来筛选分组。

GROUP BY 子句与 SELECT 语句一起使用,用于将在一个或多个列中具有相同值的行收集到汇总行中。它是 SQL 中用于分析和报告的最强大功能之一。

GROUP BY 几乎总是与 聚合函数 如 COUNT()、SUM()、AVG()、MAX() 和 MIN() 结合使用。这些函数对一组行执行计算,并为每个分组返回一个单一的汇总值。

GROUP BY 子句位于 WHERE 子句之后,并位于 HAVING 子句和 ORDER BY 子句之前。

SELECT
column_to_group_by,
aggregate_function(column_to_aggregate) AS alias
FROM
table_name
WHERE
condition -- 可选:在分组前筛选行
GROUP BY
column_to_group_by
HAVING
aggregate_condition; -- 可选:在分组后筛选分组

关键规则:SELECT 列表中出现的任何非聚合列也必须出现在 GROUP BY 子句中。忘记这一点是初学者最常见的 SQL 错误之一。

让我们使用一个示例 sales 表进行演示。此表记录了单个产品的销售情况。

CREATE TABLE sales (
order_id INT,
product_category VARCHAR(50),
region VARCHAR(50),
sale_amount DECIMAL(10, 2),
sale_date DATE
);
INSERT INTO sales VALUES
(1, 'Electronics', 'North', 1200.00, '2023-10-01'),
(2, 'Books', 'South', 55.50, '2023-10-02'),
(3, 'Electronics', 'North', 800.00, '2023-10-03'),
(4, 'Clothing', 'West', 150.00, '2023-10-03'),
(5, 'Books', 'North', 35.00, '2023-10-04'),
(6, 'Electronics', 'South', 2500.00, '2023-10-05');

让我们找出每个产品类别的总销售额。

SELECT
product_category,
SUM(sale_amount) AS total_sales
FROM sales
GROUP BY product_category;
产品类别总销售额
Electronics4500.00
Books90.50
Clothing150.00

我们可以通过按多个列分组来获得更细粒度的报告。让我们找出每个类别、每个地区的销售数量。

SELECT
product_category,
region,
COUNT(order_id) AS number_of_sales
FROM sales
GROUP BY product_category, region
ORDER BY product_category, region;
产品类别区域销售数量
BooksNorth1
BooksSouth1
ClothingWest1
ElectronicsNorth2
ElectronicsSouth1

理解 WHERE 和 HAVING 之间的区别至关重要:

  • WHERE 子句在行被分组 之前 筛选单个行。
  • HAVING 子句在聚合操作执行 之后 筛选整个分组。

让我们找出每个类别的总销售额,但仅限于“North”区域,并且仅显示总销售额超过 $100 的类别。

SELECT
product_category,
SUM(sale_amount) AS total_sales
FROM sales
WHERE region = 'North' -- 步骤 1:在分组前筛选行
GROUP BY product_category
HAVING SUM(sale_amount) > 100; -- 步骤 2:在分组后筛选分组

在此示例中,来自“North”区域的“Books”销售额为 $35.00,因此它被 HAVING 子句筛选掉了。

产品类别总销售额
Electronics2000.00

高级主题:窗口函数作为替代方案

Section titled “高级主题:窗口函数作为替代方案”

现代 SQL 提供了 窗口函数,它们可以在不折叠行的情况下执行类似聚合的计算。它们对于计算运行总计或在组内对结果进行排名等任务非常强大。

例如,要显示每个单独的销售额以及其类别的总销售额:

SELECT
product_category,
sale_amount,
SUM(sale_amount) OVER (PARTITION BY product_category) AS category_total_sales
FROM sales;

此查询使用窗口函数在同一行中同时显示详细信息(单个 sale_amount)和汇总信息(category_total_sales),这是单独使用 GROUP BY 无法实现的。