SQL Server 基础知识:使用 SQL GROUP BY 子句

SQL Server的T-SQL查询语言具有丰富的数据检索选项。这包括查询SQL数据库的能力,以及提供求和函数、计数聚合函数和分组列。SQL GROUP BY子句可以利用所有这些功能。在本文中,我将向您展示如何使用GROUP BY子句单独或与其中一个聚合函数结合使用来执行基于分组的计算。

SQL GROUP BY子句如何工作?

SQL GROUP BY子句与SELECT语句一起用于将数据排列成相同数据的组。它跟在SELECT语句的WHERE子句之后。

广告

这个子句通常与SUM、COUNT、AVG、MAX或MIN等聚合函数一起使用,这些函数允许您对分组数据进行计算。您可以按任何不同的列类型对数据进行分组,包括产品ID、日期或描述等字符。

基本的GROUP BY语法非常简单:

SELECT column1, aggregate_function(column2)
FROM table_name
GROUP BY column1;

在这里,您可以看到GROUP BY子句与基本SELECT语句一起使用。SELECT语句检索两列,第二列使用聚合函数。

技术上并不要求使用聚合函数,但它通常与GROUP BY子句结合使用。将对第一列中的数据执行分组。

广告

让我们深入了解并看看GROUP BY子句的实际应用。

使用带有SELECT语句的SQL GROUP BY

首先,让我们仅使用SQL GROUP BY子句与简单的SELECT语句,而不添加聚合函数。以下清单从SalesLT.SalesOrderDetail表中检索并对“Product ID”列进行分组在AdventureWorksLT2019示例数据库中。

USE AdventureWorksLT2019;

SELECT ProductID FROM SalesLT.SalesOrderDetail
  GROUP BY ProductID;

这实质上返回了一个已订购的所有ProductIDs列表,如下图所示。

We get a list of all of the ProductIDs that have been ordered (Image credit: Petri/Michael Otey)

使用带有聚合函数的SQL GROUP BY

通常情况下,使用SQL的GROUP BY子句与聚合函数之一一起使用,以便给出计数、总计、平均值或所有已分组列的摘要。以下语句使用GROUP BY与AdventureWorksLT2019数据库中的SalesLT.Product表,以查找每个产品类别中的产品总数:

广告

USE AdventureWorksLT2019;

SELECT ProductCategoryID, COUNT(*) AS TotalProducts
  FROM SalesLT.Product
   GROUP BY ProductCategoryID;

在这个示例中,SELECT语句从SalesLT.Product表返回’ProductCategoryID’列,并使用COUNT(*)聚合函数计算每个类别中产品的数量。在这里,GROUP BY子句按’ProductCategoryID’分组结果,而SELECT COUNT函数计算每个产品类别中产品的总数。COUNT(*)函数的结果使用别名’TotalProducts’。

此查询的结果如下图所示。此输出显示了每个产品类别中的产品总数,这是使用GROUP BY子句计算的。摘要信息由COUNT(*)聚合函数返回。

Using SQL GROUP BY with aggregate functions (Image credit: Petri/Michael Otey)

使用SQL GROUP BY与多个列

SQL的GROUP BY功能不仅限于与单个列一起工作。它还可以在同一查询中同时与多个列一起使用。

让我们来看一个在AdventureWorksLT2019数据库的SalesLT.Product表中,使用GROUP BY子句和两个列的示例。以下查询显示了如何检索每个产品类别和产品型号的产品总数。

USE AdventureWorksLT2019;

SELECT ProductCategoryID, ProductModelID, COUNT(*) AS TotalProducts
  FROM SalesLT.Product
  GROUP BY ProductCategoryID, ProductModelID;

在这里,’ProductCategoryID’和’ProductModelID’列都被检索出来,我们使用COUNT(*)聚合函数来计算每个产品类别和子类别中产品的数量。在这个例子中,GROUP BY子句对’ProductCategoryID’和’ProductModelID’列的结果进行了分组。这样就基于两个不同的列创建了两个不同的分组。

您可以在以下图表中看到此查询的结果。这些结果显示了产品和产品型号的总数,并使用列别名TotalProducts检索到总数。

Using SQL GROUP BY with multiple columns (Image credit: Petri/Michael Otey)

使用SQL GROUP BY与HAVING子句

GROUP BY子句的另一个常见用法是与HAVING子句结合使用。的确,您可以使用GROUP BY子句与HAVING子句,根据HAVING子句应用于数据分组的条件来过滤查询的结果。该条件可以应用于常规数据类型列或聚合函数。

让我们来看一个在AdventureWorksLT2019数据库中使用SQL GROUP BY子句和HAVING子句的示例。该示例显示了哪些客户在SalesLT.SalesOrderHeader表中下了订单,订单总金额大于$2000。在这里,GROUP BY子句用于按客户对订单进行分组,然后HAVING子句基于总订单金额筛选客户。

USE AdventureWorksLT2019;

SELECT  c.CustomerID, c.FirstName, c.LastName, SUM(soh.TotalDue) AS TotalOrderAmount
  FROM SalesLT.Customer c
 JOIN SalesLT.SalesOrderHeader soh ON c.CustomerID = soh.CustomerID
  GROUP BY c.CustomerID, c.FirstName, c.LastName
 HAVING SUM(soh.TotalDue) > 2000;
  • 在这段代码清单中,SalesLT.Customer表与SalesLT.SalesOrderHeader表在’CustomerID’列上进行了连接。
  • SELECT列表检索’CustomerID’、’FirstName’、’LastName’和’TotalOrderAmount’。
  • GROUP BY子句用于按客户对结果进行分组。
  • SUM()聚合函数计算每个客户的总订单金额。
  • HAVING子句筛选分组结果,只选择总订单金额大于$2000的客户。

您可以在以下图表中看到此代码清单的结果:

Using SQL GROUP BY with the HAVING clause (Image credit: Petri/Michael Otey)

使用SQL GROUP BY与ORDER BY子句

您还可以使用SQL的GROUP BY子句与ORDER BY子句一起,按一个或多个列对结果集进行排序。以下示例使用AdventureWorksLT2019数据库。为了演示ORDER BY子句与GROUP BY子句的用法,您可以简单地取上一个示例代码,并添加ORDER BY子句以按降序显示最大订单金额的结果。

USE AdventureWorksLT2019;

SELECT  c.CustomerID, c.FirstName, c.LastName, SUM(soh.TotalDue) AS TotalOrderAmount
  FROM SalesLT.Customer c
   JOIN SalesLT.SalesOrderHeader soh ON c.CustomerID = soh.CustomerID
  GROUP BY c.CustomerID, c.FirstName, c.LastName
   HAVING SUM(soh.TotalDue) > 2000
   ORDER BY TotalOrderAmount DESC;

您可以在以下图中看到结果。这些结果显示按降序列出了订单超过$2000的客户名单,最大订单金额的客户排在最前面。

Using SQL GROUP BY with the ORDER BY clause (Image credit: Petri/Michael Otey)

如您所见,使用SQL的GROUP BY子句可以实现许多功能。我向您展示了GROUP BY子句如何与多个列一起使用,以及如何添加HAVING和ORDER BY子句来过滤和排序结果。

如果有任何关于SQL的GROUP BY子句的问题,请随时提问。如果您想了解更多关于SQL Server的知识,请查看我SQL Server基础系列中的先前文章。

Source:
https://petri.com/sql-group-by/