SQL查询入门(下篇)

简介:
引言

      在前两篇文章中,对于单表查询和多表查询的概念做出了详细的介绍,在本篇文章中会主要介绍聚合函数的使用和数据的分组.

 

简介

      简单的说,聚合函数是按照一定的规则将多行(Row)数据汇总成一行的函数。对数据进行汇总前,还可以按照特定的列(column)将数据进行分组(Group by)再汇总,然后按照再次给定的条件进行筛选(Having).

 

      聚合函数将多行数据进行汇总的概念可以简单用下图解释:

       1

 

 

简单聚合函数

       简单聚合函数是那些拥有很直观将多行(Row)汇总为一行(Row)计算规则的函数。这些函数往往从函数名本身就可以猜测出函数的作用,而这些函数的参数都是数字类型的。简单聚合函数包括:Avg,Sum,Max,Min.

       简单聚合函数的参数只能是数字类型,在SQL中,数字类型具体包括:tinyint,smallint,int,bigint,decimal,money,smallmoney,float,real.

       在介绍简单聚合函数之前,先来介绍一下Count()这个聚合函数.

 

      Count()

       Count函数用于计算给定条件下所含有的行(Row)数.例如最简单的:

        2

       上表中,我想知道公司员工的个数,可以简单的使用:

SELECT     COUNT(*) AS EmployeeNumber
FROM         HumanResources.Employee
    

        结果如下

        3

         当Count()作用于某一特定列(Column),和以“*”作为参数时的区别是当Count(列名)碰到“Null”值时不会将其计算在内,例如:

        我想知道公司中有上级的员工个数:

SELECT     COUNT(ManagerID) AS EmployeeWithSuperior
FROM       HumanResources.Employee
       ceo

 

       4

       可以看到,除了没有上级的CEO之外,所有其他的员工已经被统计在内.

         

       也可以在Count()内使用Distinct关键字来让,每一列(Column)的每个相同的值只有一个被统计在内,比如:

       我想统计公司中经理层级的数量:

SELECT     COUNT(DISTINCT ManagerID) AS NumberOfManager
FROM       HumanResources.Employee
          5
       结果如上.

 

        Avg(),Sum(),Max()和Min()

        这几个聚合函数除了功能不同以外,参数和用法几乎相同。所以这里只对Avg()这个聚合函数进行解释:

        Avg()表示计算在选择范围内的汇总数据的平均值.这个过程中“Null”值不会被统计在内 ,例如:

        我想获得平均每位员工休假的时长:

SELECT     AVG(VacationHours) AS 'Average vacation hours'
FROM       HumanResources.Employee
        结果如下:

      6

      因为默认用聚合函数进行数据汇总时,不包含null,但如果我想要包含null值,并在当前查询中将Null值以其他值替代并参与汇总运算时,使用IsNull(column,value)

      例如:

      我想获得平均每位员工的休假时长,如果员工没有休假,则按休假10个小时计算

SELECT     AVG(ISNULL(VacationHours, 10)) AS  'Average vacation hours'
FROM       HumanResources.Employee
      结果如下:

      7

     也可以使用DISTINCT关键字在简单聚合函数中让每一个值唯一参与聚合汇总运算.在上面的Count函数中已经解释,这里不做重复。

     而关于Sum(),Max(),Min()等这些简单聚合函数,使用方法基本相同,这里就不重复了

 

    

将聚合函数得到的值按照列(Column)进行分组

      如果聚合函数所得到的结果无法按照特定的值进行分组,那聚合函数的作用就没那么强了。在SQL中,使用Group by对聚合函数汇总的值进行分组。分组的概念可以下面这个简单的例子表示:

       例如:

       我想根据不同省得到销售人员所销售的总和:

SELECT     TerritoryID, SUM(SalesLastYear) AS ToTalSales
FROM       Sales.SalesPerson
GROUP BY   TerritoryID
      概念如下图所示:

       8

     

   跟在Group by后面的列名是分组的依据。当然在某些情况下,会有依据多个列(Column)进行分组的情况.下面这个例子有点实际意义:

   我想按照不同性别获得不同经理手下的员工的病假时间总和:

 

SELECT     ManagerID, Gender, SUM(SickLeaveHours) AS SickLeaveHours, COUNT(*) AS EmployeeNumber
FROM       HumanResources.Employee
GROUP BY   Gender, ManagerID
  

   结果如下:

     9

     Group By后面多列,我们可以在逻辑思维上这么想,先根据每一列唯一的ManagerId和唯一的Gender进行Cross Join(如果你不懂什么Cross join,请看我前面的文章)得到唯一可以确定其他键(Key)的键,最后过滤掉聚合函数中不能返回值的行(Row)(也就是为Null)的行。再根据这实际上两列,但逻辑上是一列的值作为分组依据。

     上图中可以看到,我们首先按照经理ID,进行分组,然后根据不同经理手下的员工的性别,再次进行分总,最终按照这个分组条件得到病假时间总和.

     这里要注意,当使用Group By按照多列(Column)进行分组时,一定要注意出现在Group By后面的次序

     上面先出现Gender是先遍历Gender的所有可能的值,再根据每个Gender可能的值去计算匹配ManagerID,最后再根据ManagerID来进行聚合函数运算,如果将上面Group By后面得列(Column)顺序改为先ManagerId,再Gender,则意味着先遍历ManagerID所有可能出现的值,再去匹配Gender,则结果如下:

     10

     从Gender(性别)变为M(男性)开始,第二次遍历ManagerId进行匹配:

      11

 

     从上面我们可以看出,虽然Group by后面出现列(Column)的次序不同,所得到结果的顺序也不同,但所得到的数据集(DataSet)是完全一样,所以,可以通过Order By子句将按照不同列次序进行Group By的查询语句获得相同的结果。这里就不再截图了。

 

对分组完成后的数据集进行再次筛选(Having) 

      当对使用聚合函数进行分组后,可以再次使用放在Group By子句后的Having子句对分组后的数据进行再次的过滤.Having子句在某些方面很像Where子句,具体having表达式的使用可以看我前面文章中对where的讲解。Having子句可以理解成在分组后进行二次过滤的语句.

      使用having子句非常简单,但需要注意的是,having子句后面不能跟在select语句中出现的别名,而必须将Select语句内的表达式再写一遍,例如还是针对上面的表:

      我想按照不同性别获得不同经理手下的员工的病假时间总和,这些经理手下的员工需要大于2个人:

SELECT     ManagerID, Gender, SUM(SickLeaveHours) AS SickLeaveHours, COUNT(*) AS EmployeeNumber
FROM       HumanResources.Employee
GROUP BY   ManagerID, Gender
HAVING     (EmployeeNumber > 2)
      注意,上面这句话是错误的,在Having子句后面不能引用别名或者变量名,如果需要实现上面那个效果,需要将Count(*)这个表达式再Having子句中重写一遍,正确写法如下:

SELECT     ManagerID, Gender, SUM(SickLeaveHours) AS SickLeaveHours, COUNT(*) AS EmployeeNumber
FROM       HumanResources.Employee
GROUP BY   ManagerID, Gender
HAVING     (COUNT(*) > 2)
       结果如下:

      12

      我们看到,只有员工数大于2人的条件被选中。

 

      当然,Having子句最强大的地方莫过于其可以使用聚合函数作为表达式,这是在Where子句中不允许的。下面这个例子很好的演示了Having子句的强大之处:

      还是上面那个例子的数据:

      我想获得不同经理手下的员工的病假时间总和,并且这个经理手下病假最多的员工的请假小时数大于病假最少员工的两倍:

SELECT     ManagerID, SUM(SickLeaveHours) AS TotalSickLeaveHours, COUNT(*) AS EmployeeNumber
FROM       HumanResources.Employee
GROUP BY   ManagerID
HAVING      (MAX(SickLeaveHours) > 2 * MIN(SickLeaveHours))
   

     结果如下:

     13

 

     这里可以看出,Having子句实现如此简单就能实现的强大功能,如果用where将会非常非常的麻烦。上面那个结果中,having语句聚合函数的作用范围可以用下图很好的演示出来:

     14

     上面可以看出被筛选后的数据满足请假最多员工的小时数明显大于请假最少员工小时数的两倍。

 

小结

      本文以聚合函数概念为开始,讲述了聚合函数使用中经常用到的查询,分组,过滤的概念和使用方式。使用好聚合函数可以将很多放到应用程序业务层的任务转到数据库里来.这会对维护和性能提升很很大的帮助.

 

PS:SQL查询入门就写完了,虽然文章讲的内容很浅,但我在写作的过程中脑中很多模糊的概念变得逐渐清晰。从而对自己也是一次再学习。我也努力将每一个概念以简单的方式表现出来。技术文章就应该这样吧:-) 后续文章准备中ing….

分类: T-SQL
标签: T-SQL 入门, 聚合函数



本文转自CareySon博客园博客,原文链接:http://www.cnblogs.com/CareySon/archive/2011/05/18/2049727.html如需转载请自行联系原作者

相关文章
|
3天前
|
SQL 资源调度 数据库
深入探究SQL查询语句执行过程
深入探究SQL查询语句执行过程
15 2
|
4天前
|
SQL Java
使用java在未知表字段情况下通过sql查询信息
使用java在未知表字段情况下通过sql查询信息
11 1
|
27天前
|
SQL 存储 缓存
高基数 GroupBy 在 SLS SQL 中的查询加速
本文详细介绍了SLS中的高基数GroupBy查询加速技术。
|
21天前
|
SQL 安全 数据库
从入门到精通:Python Web安全守护指南,SQL注入、XSS、CSRF全防御!
【9月更文挑战第13天】在开发Python Web应用时,安全性至关重要。本文通过问答形式,详细介绍如何防范SQL注入、XSS及CSRF等常见威胁。通过使用参数化查询、HTML转义和CSRF令牌等技术,确保应用安全。附带示例代码,帮助读者从入门到精通Python Web安全。
45 6
|
26天前
|
SQL 运维 程序员
一个功能丰富的SQL审核查询平台
一个功能丰富的SQL审核查询平台
|
8天前
|
SQL
SQL: 巧妙使用CASE WHEN实现查询
文章演示了如何利用SQL中的CASE WHEN语句来有效地进行条件性聚合查询,通过具体示例展示了CASE WHEN在统计分析中的应用技巧。
21 0
|
2月前
|
Java 数据库连接 数据库
告别繁琐 SQL!Hibernate 入门指南带你轻松玩转 ORM,解锁高效数据库操作新姿势
【8月更文挑战第31天】Hibernate 是一款流行的 Java 持久层框架,简化了对象关系映射(ORM)过程,使开发者能以面向对象的方式进行数据持久化操作而无需直接编写 SQL 语句。本文提供 Hibernate 入门指南,介绍核心概念及示例代码,涵盖依赖引入、配置文件设置、实体类定义、工具类构建及基本 CRUD 操作。通过学习,你将掌握使用 Hibernate 简化数据持久化的技巧,为实际项目应用打下基础。
66 0
|
2月前
|
SQL 数据库 Java
HQL vs SQL:谁将统治数据库查询的未来?揭秘Hibernate的神秘力量!
【8月更文挑战第31天】Hibernate查询语言(HQL)是一种面向对象的查询语言,它模仿了SQL的语法,但操作对象为持久化类及其属性,而非数据库表和列。HQL具有类型安全、易于维护等优点,支持面向对象的高级特性,内置大量函数,可灵活处理查询结果。下面通过示例对比HQL与SQL,展示HQL在实际应用中的优势。例如,HQL查询“从员工表中筛选年龄大于30岁的员工”只需简单地表示为 `FROM Employee e WHERE e.age > 30`,而在SQL中则需明确指定表名和列名。此外,HQL在处理关联查询时也更为直观易懂。然而,对于某些复杂的数据库操作,SQL仍有其独特优势。
39 0
|
2月前
|
SQL 关系型数据库 MySQL
|
2月前
|
API Java 数据库连接
从平凡到卓越:Hibernate Criteria API 让你的数据库查询瞬间高大上,彻底告别复杂SQL!
【8月更文挑战第31天】构建复杂查询是数据库应用开发中的常见需求。Hibernate 的 Criteria API 以其强大和灵活的特点,允许开发者以面向对象的方式构建查询逻辑,同时具备 SQL 的表达力。本文将介绍 Criteria API 的基本用法并通过示例展示其实际应用。此 API 通过 API 构建查询条件而非直接编写查询语句,提高了代码的可读性和安全性。无论是简单的条件过滤还是复杂的分页和连接查询,Criteria API 均能胜任,有助于提升开发效率和应用的健壮性。
62 0
下一篇
无影云桌面