where,group by和having的使用时的最大区别

时间:2021-06-22 20:07:08
where,group by和having的使用时的最大区别是什么啊,我老是搞不懂,求大侠具体解释下

11 个解决方案

#1


where group by 先根据条件过滤再聚合
group  by having 聚合后再过滤条件
having 后面可以跟聚合函数
例:select id from tb group by id having count(*)>1

#2


where 是条件语句,直接运用.
group by 后面跟 having 也是条件,但它只用于统计用了聚集函数结果的条件判断,即如 sum(n)>100

#3



if object_id('tb') is not null
   drop table tb
go
create table tb
(
 id int,
 name varchar(10),
 sex varchar(10),
 kc varchar(10)
)
go
insert into tb
select 1,'张三','男','语文' union all
select 2,'张三','男','数学' union all
select 3,'张三','男','英语' union all
select 4,'李四','女','数学' union all
select 5,'王五','男','化学' union all
select 6,'王五','男','物理'
go
select name,cnt=count(*) from tb where sex='男' group by name having count(*)>=3
--上面的这句SQL可以拆分成几分部分分别执行一下看看效果
--1.select name from tb where sex='男'  where过滤结果集,只保留性别为男的人
--2.select name,count(*) from tb where sex='男' group by name 先使用where过滤结果集,只保留性别为男的人,然后再执行group by 按name进行分组,在选择列中使用count(*)统计每一组中的行数
--3.select name,count(*) from tb where sex='男' group by name 先使用where过滤结果集,只保留性别为男的人,然后再执行group by 按name进行分组,在选择列中使用count(*)统计每一组中的行数,再在这个基础上用having过滤掉每一组行数<3的行

#4


注意:select 后的字段,必须要么包含在group by中,要么包含在having 后的聚合函数里。
1. GROUP BY 是分组查询, 一般 GROUP BY 是和聚合函数配合使用
group by 有一个原则,就是 select 后面的所有列中,没有使用聚合函数的列,必须出现在 group by 后面(重要)


例如,有如下数据库表:

A    B 
1    abc 
1    bcd 


1    asdfg

 如果有如下查询语句(该语句是错误的,原因见前面的原则)

select A,B from table group by A  


该查询语句的意图是想得到如下结果(当然只是一相情愿) 


A     B 
       abc 
1     bcd 


       asdfg  

右边3条如何变成一条,所以需要用到聚合函数,如下(下面是正确的写法):

select A,count(B) as 数量 from table group by A 
这样的结果就是 
A    数量 
1    3  


 

2. Having

where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行。


having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚组函数,使用having 条件显示特定的组,也可以使用多个分组标准进行分组。

having 子句被限制子已经在SELECT语句中定义的列和聚合表达式上。通常,你需要通过在HAVING子句中重复聚合函数表达式来引用聚合值,就如你在SELECT语句中做的那样。例如:


SELECT A COUNT(B) FROM TABLE GROUP BY A HAVING COUNT(B)>2

 

3.使用compute和compute by
  使用compute子句允许同时观察查询所得到各列的数据的细节以及统计各列数据所产生的汇总列
      select * from work [查询所得到的各列的数据的细节]
      compute max(基本工资),min(基本工资) [统计之后的结果]
  这个例子中没有使用by关键字,返回的结果是最后添加了一行基本工资的最大值和最小值,也可增加by关键字.
        例:select * from work order by 学历
           compute max(基本工资),min(基本工资) by 学历
        比较:select 学历,max(基本工资),min(基本工资) from work group by 学历
        说明:1:compute子句必须与order by子句用在一起
             2:compute子句可以返回多种结果集.一种是体现数据细节的数据集,可以按分类要求进行正确的分类;另一种在分类的基础上进行汇总产生结果.
             3:而group by子句对每一类数据分类之后只能产生一个结果,不能知道细节

 

示例学习Northwind数据库:

非相关查询:

1:返回每个美国员工都为其处理过订单的所有客户

--思路:1:Employees表中获取美国员工总数2:Orders表中查询美国员工处理的Order,对CustomerID分组后,统计其不同的EmployeeID正好等于美国员工总数

Select CustomerID From Orders Where EmployeeID In         --得到美国员工服务 的客户

(Select EmployeeID From Employees Where Country=N'USA') -- 得到全部美国员工id

group by CustomerID                                         --按客户分组

Having Count(Distinct EmployeeID)=                    --为其处理订单的distinct 员工数等于美国总员工数

(Select Count(*) From Employees Where Country=N'USA')--美国员工总数

2:

返回在每月最后实际订单日期发生的订单(每月最后订单日期可能不是每月最后一天) 

--思路:子查询按月分组得到每月最近订单日期

Select OrderID,CustomerID,EmployeeID,OrderDate

From Orders

Where OrderDate In

(Select Max(OrderDate) From Orders Group by Convert(char(6),OrderDate,112))--112表示YYYYMMDD char(6)提取YYYYMM

 

 3.

Select字句在逻辑上是SQL语句最后进行处理的最后一步,所以,以下查询会发生错误:

SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM (SELECT YEAR(OrderDate) AS OrderYear, CustomerID
   FROM dbo.Orders) AS D
GROUP BY OrderYear 
;因为group by是在Select之前进行的,那个时候orderYear这个列并没有形成。


如果要查询成功,可以像下面进行修改:

SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM (SELECT YEAR(OrderDate) AS OrderYear, CustomerID
   FROM dbo.Orders) AS D
GROUP BY OrderYear;还有一种很特殊的写法:

SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM (SELECT YEAR(OrderDate), CustomerID
   FROM dbo.Orders) AS D(OrderYear, CustomerID)
GROUP BY OrderYear;在作者眼里,他是非常喜欢这种写法的,因为更清晰,更明确,更便于维护。


在查询中使用参数定向产生一批结果,这个技巧没有什么好说的。


嵌套查询,在处理逻辑上是从里向外进行执行的

#5


where group by 先根据条件过滤
having 聚合后再过滤条件

#6


SELECT 陳述式中的 WHERE 與 HAVING 子句控制了用來建立結果集之來源資料表的資料列。WHERE 與 HAVING 都是篩選。
GROUP BY 子句可替結果集的每個資料列產生彙總值。

#7


在实践中,查询的实际物理处理可能与逻辑处理有很大不同。
1、FROM 
2、ON
3、JOIN--做笛卡尔乘积
4、WHERE
5、GROUP BY
6、WITH(cube | rollup )
7、HAVING
8、SELECT 列表
9、DISTINCT
10、ORDER BY
逻辑查询处理的步骤序号:
(8) SELECT (9) DISTINCT (11) <TOP_specification> <select_list> 
(1) FROM <left_table> 
(3) <join_type> JOIN <right_table> 
(2) ON <join_condition> 
(4) WHERE <where_condition> 
(5) GROUP BY <group_by_list>
(6) WITH {CUBE | ROLLUP} 
(7) HAVING <having_condition> 
(10) ORDER BY <order_by_list>
看执行的先后顺序。

#8


学习了,留下有空慢慢看!

#9


在select 语句中可以使用group by 子句将行划分成较小的组,然后,使用聚组函数返回每一个组的汇总信息,另外,可以使用having子句限制返回的结果集。group by 子句可以将查询结果分组,并返回行的汇总信息Oracle 按照group by 子句中指定的表达式的值分组查询结果。
   在带有group by 子句的查询语句中,在select 列表中指定的列要么是group by 子句中指定的列,要么包含聚组函数
   select max(sal),job emp group by job; 
   (注意max(sal), job 的job并非一定要出现,但有意义 )
   查询语句的select 和group by ,having 子句是聚组函数唯一出现的地方,在where 子句中不能使用聚组函数。
  select deptno,sum(sal) from emp where sal>1200 group by deptno having sum(sal)>8500 order by deptno;
  当在gropu by 子句中使用having 子句时,查询结果中只返回满足having条件的组。在一个sql语句中可以有where子句和having子句。having 与where 子句类似,均用于设置限定条件 
 
  where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行。
  having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚组函数,使用having 条件显示特定的组,也可以使用多个分组标准进行分组。
  查询每个部门的每种职位的雇员数 
  select deptno,job,count(*) from emp group by deptno,job;
 
  如果你对何时应该使用WHERE,何时使用HAVING仍旧很迷惑,请遵照下面的说明:   

  WHERE语句在GROUP BY语句之前;SQL会在分组之前计算WHERE语句。   

  HAVING语句在GROUP BY语句之后;SQL会在分组之后计算HAVING语句

#10


where 是条件语句,直接运用.
group by 后面跟 having 也是条件,但它只用于统计用了聚集函数结果的条件判断,即如 sum(n)>100

#11


1.group by 后加上分组的字段,having后加聚集函数(sum,max,min,avg,count),where 后加普通的筛选条件

2.having 必须与group by 同时使用
 
3. group by 用法原则: select 后面出现的列,只能是使用了聚集函数的列,若有未使用聚集函数的列,则 这些未使用聚集函数的列必须出现在 group by 后面。

#1


where group by 先根据条件过滤再聚合
group  by having 聚合后再过滤条件
having 后面可以跟聚合函数
例:select id from tb group by id having count(*)>1

#2


where 是条件语句,直接运用.
group by 后面跟 having 也是条件,但它只用于统计用了聚集函数结果的条件判断,即如 sum(n)>100

#3



if object_id('tb') is not null
   drop table tb
go
create table tb
(
 id int,
 name varchar(10),
 sex varchar(10),
 kc varchar(10)
)
go
insert into tb
select 1,'张三','男','语文' union all
select 2,'张三','男','数学' union all
select 3,'张三','男','英语' union all
select 4,'李四','女','数学' union all
select 5,'王五','男','化学' union all
select 6,'王五','男','物理'
go
select name,cnt=count(*) from tb where sex='男' group by name having count(*)>=3
--上面的这句SQL可以拆分成几分部分分别执行一下看看效果
--1.select name from tb where sex='男'  where过滤结果集,只保留性别为男的人
--2.select name,count(*) from tb where sex='男' group by name 先使用where过滤结果集,只保留性别为男的人,然后再执行group by 按name进行分组,在选择列中使用count(*)统计每一组中的行数
--3.select name,count(*) from tb where sex='男' group by name 先使用where过滤结果集,只保留性别为男的人,然后再执行group by 按name进行分组,在选择列中使用count(*)统计每一组中的行数,再在这个基础上用having过滤掉每一组行数<3的行

#4


注意:select 后的字段,必须要么包含在group by中,要么包含在having 后的聚合函数里。
1. GROUP BY 是分组查询, 一般 GROUP BY 是和聚合函数配合使用
group by 有一个原则,就是 select 后面的所有列中,没有使用聚合函数的列,必须出现在 group by 后面(重要)


例如,有如下数据库表:

A    B 
1    abc 
1    bcd 


1    asdfg

 如果有如下查询语句(该语句是错误的,原因见前面的原则)

select A,B from table group by A  


该查询语句的意图是想得到如下结果(当然只是一相情愿) 


A     B 
       abc 
1     bcd 


       asdfg  

右边3条如何变成一条,所以需要用到聚合函数,如下(下面是正确的写法):

select A,count(B) as 数量 from table group by A 
这样的结果就是 
A    数量 
1    3  


 

2. Having

where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行。


having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚组函数,使用having 条件显示特定的组,也可以使用多个分组标准进行分组。

having 子句被限制子已经在SELECT语句中定义的列和聚合表达式上。通常,你需要通过在HAVING子句中重复聚合函数表达式来引用聚合值,就如你在SELECT语句中做的那样。例如:


SELECT A COUNT(B) FROM TABLE GROUP BY A HAVING COUNT(B)>2

 

3.使用compute和compute by
  使用compute子句允许同时观察查询所得到各列的数据的细节以及统计各列数据所产生的汇总列
      select * from work [查询所得到的各列的数据的细节]
      compute max(基本工资),min(基本工资) [统计之后的结果]
  这个例子中没有使用by关键字,返回的结果是最后添加了一行基本工资的最大值和最小值,也可增加by关键字.
        例:select * from work order by 学历
           compute max(基本工资),min(基本工资) by 学历
        比较:select 学历,max(基本工资),min(基本工资) from work group by 学历
        说明:1:compute子句必须与order by子句用在一起
             2:compute子句可以返回多种结果集.一种是体现数据细节的数据集,可以按分类要求进行正确的分类;另一种在分类的基础上进行汇总产生结果.
             3:而group by子句对每一类数据分类之后只能产生一个结果,不能知道细节

 

示例学习Northwind数据库:

非相关查询:

1:返回每个美国员工都为其处理过订单的所有客户

--思路:1:Employees表中获取美国员工总数2:Orders表中查询美国员工处理的Order,对CustomerID分组后,统计其不同的EmployeeID正好等于美国员工总数

Select CustomerID From Orders Where EmployeeID In         --得到美国员工服务 的客户

(Select EmployeeID From Employees Where Country=N'USA') -- 得到全部美国员工id

group by CustomerID                                         --按客户分组

Having Count(Distinct EmployeeID)=                    --为其处理订单的distinct 员工数等于美国总员工数

(Select Count(*) From Employees Where Country=N'USA')--美国员工总数

2:

返回在每月最后实际订单日期发生的订单(每月最后订单日期可能不是每月最后一天) 

--思路:子查询按月分组得到每月最近订单日期

Select OrderID,CustomerID,EmployeeID,OrderDate

From Orders

Where OrderDate In

(Select Max(OrderDate) From Orders Group by Convert(char(6),OrderDate,112))--112表示YYYYMMDD char(6)提取YYYYMM

 

 3.

Select字句在逻辑上是SQL语句最后进行处理的最后一步,所以,以下查询会发生错误:

SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM (SELECT YEAR(OrderDate) AS OrderYear, CustomerID
   FROM dbo.Orders) AS D
GROUP BY OrderYear 
;因为group by是在Select之前进行的,那个时候orderYear这个列并没有形成。


如果要查询成功,可以像下面进行修改:

SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM (SELECT YEAR(OrderDate) AS OrderYear, CustomerID
   FROM dbo.Orders) AS D
GROUP BY OrderYear;还有一种很特殊的写法:

SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM (SELECT YEAR(OrderDate), CustomerID
   FROM dbo.Orders) AS D(OrderYear, CustomerID)
GROUP BY OrderYear;在作者眼里,他是非常喜欢这种写法的,因为更清晰,更明确,更便于维护。


在查询中使用参数定向产生一批结果,这个技巧没有什么好说的。


嵌套查询,在处理逻辑上是从里向外进行执行的

#5


where group by 先根据条件过滤
having 聚合后再过滤条件

#6


SELECT 陳述式中的 WHERE 與 HAVING 子句控制了用來建立結果集之來源資料表的資料列。WHERE 與 HAVING 都是篩選。
GROUP BY 子句可替結果集的每個資料列產生彙總值。

#7


在实践中,查询的实际物理处理可能与逻辑处理有很大不同。
1、FROM 
2、ON
3、JOIN--做笛卡尔乘积
4、WHERE
5、GROUP BY
6、WITH(cube | rollup )
7、HAVING
8、SELECT 列表
9、DISTINCT
10、ORDER BY
逻辑查询处理的步骤序号:
(8) SELECT (9) DISTINCT (11) <TOP_specification> <select_list> 
(1) FROM <left_table> 
(3) <join_type> JOIN <right_table> 
(2) ON <join_condition> 
(4) WHERE <where_condition> 
(5) GROUP BY <group_by_list>
(6) WITH {CUBE | ROLLUP} 
(7) HAVING <having_condition> 
(10) ORDER BY <order_by_list>
看执行的先后顺序。

#8


学习了,留下有空慢慢看!

#9


在select 语句中可以使用group by 子句将行划分成较小的组,然后,使用聚组函数返回每一个组的汇总信息,另外,可以使用having子句限制返回的结果集。group by 子句可以将查询结果分组,并返回行的汇总信息Oracle 按照group by 子句中指定的表达式的值分组查询结果。
   在带有group by 子句的查询语句中,在select 列表中指定的列要么是group by 子句中指定的列,要么包含聚组函数
   select max(sal),job emp group by job; 
   (注意max(sal), job 的job并非一定要出现,但有意义 )
   查询语句的select 和group by ,having 子句是聚组函数唯一出现的地方,在where 子句中不能使用聚组函数。
  select deptno,sum(sal) from emp where sal>1200 group by deptno having sum(sal)>8500 order by deptno;
  当在gropu by 子句中使用having 子句时,查询结果中只返回满足having条件的组。在一个sql语句中可以有where子句和having子句。having 与where 子句类似,均用于设置限定条件 
 
  where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行。
  having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚组函数,使用having 条件显示特定的组,也可以使用多个分组标准进行分组。
  查询每个部门的每种职位的雇员数 
  select deptno,job,count(*) from emp group by deptno,job;
 
  如果你对何时应该使用WHERE,何时使用HAVING仍旧很迷惑,请遵照下面的说明:   

  WHERE语句在GROUP BY语句之前;SQL会在分组之前计算WHERE语句。   

  HAVING语句在GROUP BY语句之后;SQL会在分组之后计算HAVING语句

#10


where 是条件语句,直接运用.
group by 后面跟 having 也是条件,但它只用于统计用了聚集函数结果的条件判断,即如 sum(n)>100

#11


1.group by 后加上分组的字段,having后加聚集函数(sum,max,min,avg,count),where 后加普通的筛选条件

2.having 必须与group by 同时使用
 
3. group by 用法原则: select 后面出现的列,只能是使用了聚集函数的列,若有未使用聚集函数的列,则 这些未使用聚集函数的列必须出现在 group by 后面。