Group By 和 Having, Where ,Order by语句的执行顺序:

时间:2021-09-30 20:08:57

一. group by 
1.GROUP BY子句主要用于对WHERE中得到的结果进行分组,也就是说它是在WHERE子句之后执行,对经过WHERE筛选后的结果按照某些列进行分组,之后进行相应的处理工作。 

注意:如果在返回集字段中,这些字段要么就要包含在Group By语句的后面,作为分组的依据;要么就要被包含在聚合函数中。 

eg: select agent_Code,count(domain_name) from service_domain group by agent_code 

说明:统计代理商注册域名的个数 

2.Group By All [expressions] 
如果使用 ALL 关键字,那么查询结果将包括由 GROUP BY 子句产生的所有组,即使某些组没有符合搜索条件的行。没有 ALL 关键字,包含 GROUP BY 子句的 SELECT 语句将不显示没有符合条件的行的组。 

eg: select agent_Code,count(domain_name) from service_domain where agent_code != 'agent8175' group by all agent_code 

说明:统计所有代理商注册域名的个数,如果没有all,则统计除agent8175之外的代理的注册域名的个数。 

3.GROUP BY [Expressions] WITH CUBE | ROLLUP 

首先需要说明的是Group By All 语句是不能和CUBE 和 ROLLUP 关键字一起使用的。 

cube指定在结果集内不仅包含由 GROUP BY 提供的正常行,还包含汇总行。在结果集内返回每个可能的组和子组组合的 GROUP BY 汇总行。GROUP BY 汇总行在结果中显示为 NULL,但可用来表示所有值。使用 GROUPING 函数确定结果集内的空值是否是 GROUP BY 汇总值。   结果集内的汇总行数取决于 GROUP BY 子句内包含的列数。GROUP BY 子句中的每个操作数(列)绑定在分组 NULL 下,并且分组适用于所有其它操作数(列)。由于 CUBE 返回每个可能的组和子组组合,因此不论指定分组列时所使用的是什么顺序,行数都相同。 

这个定义可以这样理解:如果是GROUP BY CUBE(A, B, C),则首先会对(A、B、C)进行GROUP BY,然后依次是(A、B),(A、C),(A),(B、C),(B),(C),最后对全表进行GROUP BY操作(即GROUP BY(0))。即:CUBE操作字,除完成ROLLUP的功能外,再对ROLLUP后的结果集从右到左再聚合,逐个减少字段。CUBE常用于需要产生交叉 报表的地方。 

eg: select agent_Code,product_code,count(domain_name) from service_domain group by  cube(agent_code ,product_code ) 

ROLLUP部分ROLLUP:你也可以使用Rollup包含有限的几个小计,其语法是:Group by A,Rollup(B,C)。这种情况下,group by 条款先计算rollup中的部分,然后加上非rollup的部分,故层次为(A,B,C)(A,B)(A)。这里去除A不看就是GROUP BY(B,C),GROUP BY(B),GROUP BY(0),刚好就是ROLLUP(B,C)部分,然后再加上A,就得到GROUP BY A,ROLLUP(B,C)。 

eg: select agent_Code,product_code,count(domain_name) from service_domain group by  rollup(agent_code ,product_code ) 

4.GROUPING SETS扩展 
也就是通过它,你就可以控制GROUP BY后面的内容。举个例子来说,如果GROUP BY A,GROUPING SETS(B,C),那么实际上就想当于GROUP BY A,B UNION ALL GROUP BY A,C。 

eg: select a,b,c,d,e,sum(c) sc from t group by a,grouping sets((b,c),(d,e)); 

5.having条件: 
eg: select agent_Code,product_code,count(domain_name) from service_domain group by  agent_code ,product_code  having count(domain_name) > 4 

二. distinct关键字 用于去重: 
1.删除重复的数据DISTINCT 关键字可从 SELECT 语句的结果中除去重复的行。如果没有指定 DISTINCT,那么将返回所有行,包括重复的行。 
eg:select distinct(domain_name),apply_date from service_domaindel 

注意:distinct必须放在开头。 

select * ,count(distinct domain_name) from service_domaindel group by domain_name 这个在mysql中支持,但是在oracle中不支持。 


三. Group By 和 Having, Where ,Order by语句的执行顺序: 
最后要说明一下的Group By, Having, Where, Order by几个语句的执行顺序。一个SQL语句往往会产生多个临时视图,那么这些关键字的执行顺序就非常重要了,因为你必须了解这个关键字是在对应视图形成前的 字段进行操作还是对形成的临时视图进行操作,这个问题在使用了别名的视图尤其重要。以上列举的关键字是按照如下顺序进行执行的:Where, Group By, Having, Order by。首先where将最原始记录中不满足条件的记录删除(所以应该在where语句中尽量的将不符合条件的记录筛选掉,这样可以减少分组的次数),然后 通过Group By关键字后面指定的分组条件将筛选得到的视图进行分组,接着系统根据Having关键字后面指定的筛选条件,将分组视图后不满足条件的记录筛选掉,然后 按照Order By语句对视图进行排序,这样最终的结果就产生了。在这四个关键字中,只有在Order By语句中才可以使用最终视图的列名,如:   SELECT FruitName, ProductPlace, Price, ID AS IDE, Discount   FROM T_TEST_FRUITINFO   WHERE (ProductPlace = N'china')   ORDER BY IDE   这里只有在ORDER BY语句中才可以使用IDE,其他条件语句中如果需要引用列名则只能使用ID,而不能使用IDE。


转载:http://tangwenchao86.iteye.com/blog/1107795