翻译6

                 通向T-SQLDML第7级的楼梯:使用一个简单的按子句分组的组来总结数据

                 发布: Gregory Larsen, 2012/01/04

该系列

本文是楼梯系列的一部分:从楼梯到T-SQLDML的楼梯。

此阶梯将为您提供如何使用SQLServer的Transact-SQL(T-SQL)方言处理来自SQLServer表的数据的基本理解。DML是一种数据操作语言,是处理数据的语言的一个方面。 它包括SELECT、INSERT、UPDATE和DELETE语句。此阶梯也会提供一些以往的SQL语言和一些有关建立学说基本的概念。每个级别都将建立在以前的级别之上,所以当您完成时,您将很好地了解如何从SQLServer中选择和修改数据。

在楼梯6中,我向您展示了如何使用ORDERBY子句对数据进行排序。这使您可以根据单个或多个列按排序顺序组织详细记录。如果要查看特定记录中的数据,详细数据是很好的,但有时需要将详细数据汇总为汇总值。总结您可以使用GROUP BY子句完成的数据。
有两种类型的组分句。一个被称为简单的GROUPBY子句,另一个提供了比简单摘要更多的内容,这就是所谓的GROUPBY子句。这两种类型之间的主要区别是简单组BY仅包含GROUP BY子句,而常规GROUP BY子句包含其他操作符,如ROLUP和CUBE。

在本文中,我将介绍如何使用简单的GROUPBY子句对数据进行分组。在一篇后续文章中,我将逐条讨论更为复杂的一般群体。

单组逐句

使用简单的GROUP BY子句,可以根据单个列、多个列或表达式聚合数据。将根据GROUP BY子句中指定的列和/或表达式为每个唯一值返回一个汇总行。当SQLServer处理GROUP BY子句时,它会根据唯一的列或表达式值对详细记录进行分组,然后根据SELECT列表中包含的聚合函数汇总每个集合。

为了更好地掌握如何使用GROUP BY,让我们假设您有一个包含不同商店的详细销售信息的表,并且您希望按商店汇总总销售额。可以使用GROUP BY子句汇总每个商店的总销售额。在本例中,要分组的唯一列是商店名称,要聚合的列是销售额。您的结果将显示每个唯一存储名的一行,而每个存储的行将包含该存储的销售金额之和 。 SQLServer在按查询在组的选择列表中包含哪些列方面有一些限制。在GROUP BY查询的SELECT列表中指定的每一列都需要归入下列类别之一:

■GROUP BY子句中指定的列。

■GROUP BY子句中指定的表达式。

■从聚合函数返回的值

如果列不属于这些类别之一,则在尝试按查询运行组时会出现错误。注意,包含在GROUPBY子句中的列或表达式不需要在SELECT列表中。

让我通过几个例子来帮助演示如何使用简单的GROUPBY子句获得汇总的值。

通过子句探索简单组的样本数据

为了演示如何使用简单的GROUPBY子句,我需要构建一些示例数据。我提供了一个脚本来创建我的示例数据,这样您就可以运行本文中提供的示例代码。使用清单1中的脚本构建和填充示例表。

USE tempdb;GO

SET NOCOUNT ON;

-- Create Sales Table   CREATE TABLE dbo.SalesTransaction

   (Id INT IDENTITY PRIMARY KEY

   ,CustomerName VARCHAR(65)

   ,TotalSalesAmount money

   ,SalesTypeDesc VARCHAR(200)

   ,SalesDateTime DATETIME

   ,StoreName VARCHAR(100));

 

   -- Add data to Sales TableINSERT INTO dbo.SalesTransaction

  VALUES('John Smith', 124.23,'Software','09/22/2011 11:51:12 AM','The Software Outlet');INSERT INTO dbo.SalesTransaction

   VALUES('Jack Thomas', 29.56,'Computer Supplies','09/23/2011 10:21:49 AM','The Software Outlet');INSERT INTO dbo.SalesTransaction

   VALUES('Sue Hunter', 89.45,'Computer Supplies','09/23/2011 2:51:56 AM','The Software Outlet');INSERT INTO dbo.SalesTransaction

           VALUES('Karla Johnson', 759.12,'Software','09/23/2011 2:54:37 PM','The Software Outlet');

      INSERT INTO dbo.SalesTransaction

 VALUES('Gary Clark', 81.51,'Software','09/22/2011 11:08:52 AM','Discount Software');INSERT INTO dbo.SalesTransaction

  VALUES('Scott Crochet', 12345.78,'Computer Supplies','09/23/2011 3:12:37 PM','Discount Software');INSERT INTO dbo.SalesTransaction

 VALUES('Sheri Holtz', 12.34,'Software','09/23/2011 10:51:42 AM','Discount Software');INSERT INTO dbo.SalesTransaction

         VALUES ('Mary Lee', 101.34,'Software','09/23/2011 09:37:19 AM','Discount Software');

      INSERT INTO dbo.SalesTransaction

 VALUES('Sally Davisson', 871.12,'Software','09/22/2011 05:21:28 PM','Discount Software');INSERT INTO dbo.SalesTransaction

  VALUES('Rod Kaplan', 2345.19,'Computer Supplies','09/23/2011 5:01:11 PM','Discount Software');INSERT INTO dbo.SalesTransaction

  VALUES('Sandy Roberts', 76.38,'Books','09/23/2011 4:51:57 PM','Computer Books and Software');INSERT INTO dbo.SalesTransaction

         VALUES ('Marc Trotter', 562.94,'Software','09/23/2011 6:51:43 PM','Computer Books and Software');

清单1:创建示例数据的脚本

如果查看清单1中的脚本,就会发现我创建了dbo.SalesTransaction表。然后,我将一些记录插入到这个表中。我将使用这个表演示如何使用简单的GROUPBY子句来聚合数据。

按单列分组

使用使用清单1创建的示例表,第一个示例将使用GROUPBY子句根据单个列总结数据。清单2中的示例总结了基于StoreName列的示例数据。

USE tempdb;

GO

SELECT StoreName

     ,SUM(TotalSalesAmount) AS StoreSalesAmount

FROM dbo.SalesTransaction  

GROUP BY StoreName;

 

清单2:基于单列的分组

当清单2中的代码针对我的示例表执行时,将返回报表1中的下列聚合行。

StoreName                                  StoreSalesAmount

------------------------------------------ ----------------

Computer Books and Software                639.32

Discount Software                          15757.28

The Software Outlet                        1002.36

报告1:基于单个列总结示例数据

如果查看报表1中的输出,您可以看到,对于StoreName的每个唯一值,只返回一个聚合行。每个记录上的StoreSalesA挂载是通过使用SUM函数对每个商店的销售记录的TotalSalesAmount列进行汇总来计算的。

按多列分组

有时,您需要开发一个报表,其中您的数据需要按多个列分组。为了实现这一点,您所需要做的就是向GROUPBY子句添加额外的列。当在GROUPBY子句中指定多个列时,SQLServer将根据GROUPBY子句中每个值的唯一组合聚合详细的行。在清单3中,我扩展了清单2中的查询,向GROUPBY子句中添加了第二列。

USE tempdb;

GO

SELECT StoreName, SalesTypeDesc

     ,SUM(TotalSalesAmount) AS StoreSalesAmount

FROM dbo.SalesTransaction  

GROUP BY StoreName, SalesTypeDesc;

清单3:基于单个列的组

当我针对我的示例数据运行清单3中的代码时,我在Report 2中得到了结果。

StoreName                    SalesTypeDesc      StoreSalesAmount

---------------------------- ------------------ ----------------

Computer Books and Software  Books              76.38

Discount Software            Computer Supplies  14690.97

The Software Outlet          Computer Supplies  119.01

Computer Books and Software  Software           562.94

Discount Software            Software           1066.31

The Software Outlet          Software           883.35

Report 2:运行清单1的输出

在报告2中,您可以看到StoreSalesAmount现在在StoreName和SalesTypeDesc级别上进行了总结。还请注意,根据GROUP BY子句中的列,返回的聚合行没有按排序顺序排列。如果我希望汇总的数据出现在StoreName顺序中,那么我就需要在SELECT语句中包含ORDERBY子句。我将让您将Orderby添加到清单3中的代码中,以返回StoreName顺序中的汇总数据。

使用组中的表达式by子句

有时,您可能希望根据特定列或列集以外的内容对数据进行分组。例如,您可能希望根据某些VARCHAR列的前几个字符,或者仅仅是DateTime列的日期或月份来总结您的数据。SQLServer允许您在GROUP BY子句中指定表达式以完成这一任务。表达式可以是基于正在聚合的详细记录集中的列的任何有效表达式。要演示如何在GROUPBY子句中使用表达式,请查看清单4中的代码。

USE tempdb;

GO

SELECT CONVERT(CHAR(10),SalesDateTime,101) AS SalesDate  

  ,SUM(TotalSalesAmount) AS TotalSalesAmount

FROM dbo.SalesTransactionGROUP BY CONVERT(CHAR(10),SalesDateTime,101);

清单4:基于单个列的组

在清单4中,SELECT语句根据表达式对数据进行分组,在本例中是一个转换函数。如果在GROUPBY子句中使用表达式,则必须在SELECT列表中使用相同的表达式。转换函数解析SalesDateTime列,并仅返回该列的日期部分。使用GROUP BY子句中的转换函数,我可以根据不同销售记录的实际日期总结销售数据。通过这样做,我能够总结我的示例,以便按日期获得所有商店的TotalesA挂载,如报告3所示。

SalesDate  TotalSalesAmount

---------- ----------------

09/22/2011 1076.86

09/23/2011 16322.10

报表3:根据表达式汇总数据时的输出

使用表达式可以让您以编程方式识别将使用详细数据的哪些部分来聚合数据。

HAVING子句

如果要使用GROUP BY子句聚合数据,则可能不希望返回所有聚合值。相反,您可能希望只返回聚合值的子集。HAVING子句可用于选择性地标识您希望通过汇总从组返回的聚合值。

通常,当我们选择数据时,我们使用WHERE子句来限制返回的行。唯一的问题是WHERE子句操作行值,而不是聚合值。因此,WHERE子句无法使用GROUP BY子句创建的聚合值。但是,在GROUP BY子句之后添加HAVING子句为您提供了一种指定条件的方法,以标识要返回的特定汇总值。为了更好地理解这一点,让我给你们举几个例子。

在查看商店销售数据时,HAVING子句可能用于确定不满足特定销售配额的商店。如果您想找到所有没有达到最低销售金额的商店,可以使用清单5中的代码来实现这一点。

USE tempdb;

GO

SELECT StoreName

     ,SUM(TotalSalesAmount) AS StoreSalesAmount

FROM dbo.SalesTransaction 

GROUP BY StoreNameHAVING SUM(TotalSalesAmount) < 1000.00;

清单5:使用HITH子句限制结果集

在清单5中,我限制那些商店有一个聚集totalsalesamount小于1000的结果。在这里我的平凡的例子,你会发现“电脑书籍和软件”是不符合1000美元的销售配额数量只存储storename。

HAVE子句可以用于未聚合的列。如果您希望根据GROUPBY子句中使用的任何列的特定值来限制返回的行,那么您也可以这样做,清单6演示了这一点。

USE tempdb;GOSELECT StoreName

     ,SUM(TotalSalesAmount) AS StoreSalesAmount

FROM dbo.SalesTransaction 

GROUP BY StoreName HAVING StoreName LIKE '%Outlet%' 

    OR StoreName LIKE '%Books%';

清单6:基于逐列组限制结果集

在清单6中,我只想看到商店名称中有“Outlet”或“Books”的商店的汇总数据,这个示例还演示了在HAVING子句中可以有多个条件。另一种思考WHERE和WITH之间区别的方法是,WHERE子句在数据聚合之前过滤掉数据行,而HAVING子句在应用GROUP BY之后过滤聚合行。

用简单组按子句总结数据

在本文中,我向您展示了如何使用简单的GROUP BY子句来总结您的数据。我讨论了如何使用单个列、多列以及GROUP BY子句中的表达式来总结详细数据。通过使用我演示的内容,您现在应该能够构建一个简单的GROUPBY子句来总结您的数据,并且可以选择地使用已有的。

在我的下一篇文章中,我将扩展我对GROUPBY子句的讨论。在这篇后续文章中,我将向您展示如何使用多维数据集和汇总操作符来生成额外的汇总数据,如小计值和总计值。

本文是T-SQLDML楼梯的一部分。

注册我们的RSS提要,并得到通知,一旦我们发布一个新的层次在楼梯上!

Keep up to date with SQL Server - new articles every day.

 

 Sign up

猜你喜欢

转载自blog.csdn.net/xtt_3170707038/article/details/80015173
今日推荐