SQL SERVER 入门进阶教程——数据分组(GROUP BY和HAVING)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zefllj/article/details/97523550

数据分组


提示:接下来学习数据分组,这样是便于汇总表的内容,分组功能涉及的两个关键字,那就是GROUP BY和HAVING。

1.1 数据分组介绍
使用SQL聚集函数可以汇总数据,这样我们就可以对其进行计数、计算和平均数,不检索所有数据就可以获得最大值和最小值。

目前为止所有的计算都是在表的所有数据或匹配特定的WHERE字句的数据上进行的,比如我们看下面的语句:

SELECT COUNT(*) AS num_prods FROM Products WHERE vend_id = 'DLL01';

输出结果

1.2 创建分组

提示:分组是使用SELECT语句中的GROUP BY字句建立的。

SQL语句:

SELECT vend_id, COUNT(*) AS num_prods FROM Products GROUP BY vend_id;

输出结果:

SQL语句分析:

上面的SELECT语句指定了两个列:vend_id包含产品供应商的ID,num_prods为计算字段(用COUNT(*)函数建立)。GROUP BY子句指示 DBMS按vend_id排序并分组数据。这就会对每个vend_id而不是整个表计算num_prods一次。从输出中可以看到,供应商BRS01有3个产品,供 应商DLL01有4个产品,而供应商FNG01有2个产品。

说明:

因为使用了GROUP BY,就不必指定要计算和估值的每个组了。系统会自动完成。GROUP BY子句指示DBMS分组数据,然后对每个组而不是整 个结果集进行聚集。

在使用GROUP BY子句前,需要知道一些重要的规定。

  • GROUP BY子句可以包含任意数目的列,因而可以对分组进行嵌套,更细致地进行数据分组。 

  • 如果在GROUP BY子句中嵌套了分组,数据将在最后指定的分组上进行汇总。换句话说,在建立分组时,指定的所有列都一起计算(所以 不能从个别的列取回数据)。

  •  GROUP BY后面的子句中列出的每一列都必须是检索列或有效的表达式(但不能是聚集函数)。如果在SELECT中使用表达式,则必须在GROUP BY子句中指定相同的表达式。不能使用别名。 

  • 在SELECT后面的字句中除GROUP BY分组指定的列名外,都必须使用聚集函数,否则会报错,这是新手很容易犯得错误。

  • 大多数SQL实现不允许GROUP BY列带有长度可变的数据类型(如文本或备注型字段)。 

  • 在GROUP BY后面的分组条件,必须在SELECT后面列出,不用添加聚集函数。

  •  如果分组列中包含具有NULL值的行,则NULL将作为一个分组返回。如果列中有多行NULL值,它们将分为一组。 

  • GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。

提示:GROUP BY语句相对初学者来说比较难理解,我就在这上面吃了好些亏,当掌握了以后其实也很容易理解,关键就是多使用,在使用中去理解语句的含义。

1.3 分组过滤

GROUP BY是进行数据分组,当然分组后也可以根据分组信息进行过滤,这就需要HAVING了,HAVING和WHERE非常类似,接着我们介绍一下WHERE和HAVING的区别:

  • WHERE过滤指定的行而不是组,HAVING过滤的是组,这是他们的本质区别

  • HAVING支持所有WHERE的操作符,我们前面所学的所有有关WHERE技术和选项都是用与HAVING,他们的语句是相同的,只是关键字有差别。

  • WHERE是在数据分组前进行过滤,HAVING是在数据分组后进行过滤,也就意味这当WHERE和HAVING在同一条语句中时,WHERE应在HAVING语句前面。

SQL语句:

SELECT cust_id, COUNT(*) AS orders FROM Orders GROUP BY cust_id HAVING COUNT(*) >= 2;

SQL语句分析:

这条SELECT语句的前三行类似于上面的语句。最后一行增加了HAVING子句,它过滤COUNT(*) >= 2(两个以上订单)的那些分组。我们将此条语句分开来说,HAVING语句之前是根据列cust_id进行分组来统计数量,HAVING语句是根据分组后的数据在进行过滤。

输出结果:

下面我们将WHERE和HAVING放到统一语句中使用

SQL语句:

SELECT vend_id, COUNT(*) AS num_prods FROM Products 
WHERE prod_price >= 4 
GROUP BY vend_id 
HAVING COUNT(*) >= 2;

SQL语句分析:

这条语句中,第一行是使用了聚集函数的基本SELECT语句,很像前面的例子。WHERE子句过滤所有prod_price至少为4的行,然后按vend_id分 组数据,HAVING子句过滤计数为2或2以上的分组

输出结果:

 

展开阅读全文

sql分组查询,group by count(*) having 数据重复

01-04

单条语句查询rn(select org1.name as orgname, COUNT(DISTINCT employeeid) from t_hr_emponduty as em1 rnleft join t_hr_org as org1 on org1.id=em1.orgid where employeeid not in('','NULL') rnand ondutydate BETWEEN CONVERT(datetime,'2011-11-1') and CONVERT(datetime,'2011-11-30') rngroup by org1.name)rn结果:rnname number1rn1 1rn2 3rn3 1rnrn拼了三条语句:rnselect org.name,rn(select COUNT(DISTINCT employeeid) from t_hr_emponduty as em1 rnleft join t_hr_org as org1 on org1.id=em1.orgid where employeeid not in('','NULL') rnand ondutydate BETWEEN CONVERT(datetime,'2011-11-1') and CONVERT(datetime,'2011-11-30') rn) as number1,rn(select COUNT(DISTINCT employeeid) from t_hr_emponduty as em2 rnleft join t_hr_org as org2 on org2.id=em2.orgid left join t_hr_employee as ep2 on ep2.id=em2.employeeid where employeeid not in('','NULL') rnand em2.positivedate BETWEEN CONVERT(datetime,'2011-11-1') and CONVERT(datetime,'2011-11-30') rnand ep2.matriculatesource='402848b62569c53901256d0d8c332110' ) as number2,rn(select COUNT(DISTINCT employeeid) from t_hr_emponduty as em3 rnleft join t_hr_org as org3 on org3.id=em3.orgid left join t_hr_employee as ep3 on ep3.id=em3.employeeid where employeeid not in('','NULL') rnand em3.positivedate BETWEEN CONVERT(datetime,'2011-11-1') and CONVERT(datetime,'2011-11-30') rnand ep3.matriculatesource='402848b62569c53901256d0d8c3321e9' ) as number3 rnfrom t_hr_org as org,t_hr_emponduty as em where rnorg.id=em.orgid rngroup by org.name having count(*)>1rnrn正确的查询结果应为:rnname  number1 number2 number3rnxxx 6 0 0rnaaaa 0 0 0rn。。。。。。。。。。。。。。。。。。。。rn可是照我上面的语句查询结果为rnname  number1 number2 number3rnxxx 6 0 0rnaaaa 6 0 0rncccc 6 0 0rndddd 6 0 0rnrn但是我查询出的每行number都要对应一个name,所以就只有在外层匹配org.name了,后面还有十几条查询number的语句。每个number都是所属一个org.name的一个汇总,现在只是分了很多种状态把它查询出来,再对应到所属的org.name 论坛

SQL教程Group byHaving

04-09

rn在介绍GROUP BY 和 HAVING 子句前,我们必需先讲讲sql语言中一种特殊的函数:聚合函数,例如SUM, COUNT, MAX, AVG等。这些函数和其它函数的根本区别就是它们一般作用在多条记录上。 SELECT SUM(population) FROM bbc rnrnrn这里的SUM作用在所有返回记录的population字段上,结果就是该查询只返回一个结果,即所有国家的总人口数。rnrn通过使用GROUP BY 子句,可以让SUM 和 COUNT 这些函数对属于一组的数据起作用。当你指定 GROUP BY region 时, 属于同一个region(地区)的一组数据将只能返回一行值,也就是说,表中所有除region(地区)外的字段,只能通过 SUM, COUNT等聚合函数运算后返回一个值。rnrnHAVING子句可以让我们筛选成组后的各组数据,WHERE子句在聚合前先筛选记录.也就是说作用在GROUP BY 子句和HAVING子句前.rnrn而 HAVING子句在聚合后对组记录进行筛选。rnrn让我们还是通过具体的实例来理解GROUP BY 和 HAVING 子句。rnrnSQL实例:rnrn一、显示每个地区的总人口数和总面积: SELECT region, SUM(population), SUM(area)rnrnFROM bbcrnrnGROUP BY region rnrnrn先以region把返回记录分成多个组,这就是GROUP BY的字面含义。分完组后,然后用聚合函数对每组中的不同字段(一或多条记录)作运算。rnrn二、 显示每个地区的总人口数和总面积.仅显示那些面积超过1000000的地区。 SELECT region, SUM(population), SUM(area)rnrnFROM bbcrnrnGROUP BY regionrnrnHAVING SUM(area)>1000000 rnrnrn在这里,我们不能用where来筛选超过1000000的地区,因为表中不存在这样一条记录。rnrn相反,HAVING子句可以让我们筛选成组后的各组数据rnrn 转http://database.51cto.com/ 论坛

没有更多推荐了,返回首页