sql中having语句的使用(这篇是从借鉴别人的文章,但是忘了具体出处)

HAVING用法详解

  • HAVING 子句对 GROUP BY 子句设置条件的方式与 WHERE 和 SELECT 的交互方式类似。
  • WHERE 搜索条件在进行分组操作之前应用;而 HAVING 搜索条件在进行分组操作之后应用。三个条件的执行顺序
  • HAVING 语法与 WHERE 语法类似,但 HAVING 可以包含聚合函数。HAVING 子句可以引用选择列表中显示的任意项。

下面的示例按产品 ID 对 SalesOrderDetail 进行了分组,并且只包含那些订单合计大于 $1,000,000 且其平均订单数量小于 3 的产品组。

USE AdventureWorks;

GO

SELECT ProductID, AVG(OrderQty) AS AverageQuantity, SUM(LineTotal) AS Total

FROM SalesOrderDetail

GROUP BY ProductID

HAVING SUM(LineTotal) > 1000000.00

AND AVG(OrderQty) < 3 ;

GO

请注意,如果 HAVING 中包含多个条件,那么这些条件将通过 AND、OR 或 NOT 组合在一起。

若要查看总销量大于 $2,000,000 的产品,请使用下面的查询:

USE AdventureWorks;


SELECT ProductID, SUM(LineTotal) Total

FROM SalesOrderDetail

GROUP BY ProductID

HAVING SUM(LineTotal) > $2000000.00 ;

GO

下面是结果集:
 

ProductID   Total

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

781         3864606.54937208

969         2010943.97244001

793         2897478.01200001

784         3699803.72383008

780         3880441.60780208

976         2079038.42948

795         2268057.09000002

783         4548164.01783709

779         4170215.3849281

782         5032968.13026809

794         2679200.01336002

753         2006264.4236

(12 row(s) affected)

若要确保对每种产品的计算中至少包含 1500 项,请使用 HAVING COUNT(*) > 1500 消除返回的销售总数小于 1500 项的产品。该查询类似于下面的示例:


USE AdventureWorks;

GO

SELECT ProductID, SUM(LineTotal) AS Total

FROM SalesOrderDetail

GROUP BY ProductID

HAVING COUNT(*) > 1500 ;

GO

理解应用 WHERE、GROUP BY 和 HAVING 子句的正确顺序对编写高效的查询代码会有所帮助:

WHERE 子句用来筛选 FROM 子句中指定的操作所产生的行。

GROUP BY 子句用来分组 WHERE 子句的输出。

HAVING 子句用来从分组的结果中筛选行。

对于可以在分组操作之前或之后应用的任何搜索条件,在 WHERE 子句中指定它们会更有效。这样可以减少必须分组的行数。
应当在 HAVING 子句中指定的搜索条件只是那些必须在执行分组操作之后应用的搜索条件。

Microsoft SQL Server 2005 查询优化器可以处理这些条件中的大多数条件。
如果查询优化器确定 HAVING 搜索条件可以在分组操作之前应用,那么它就会在分组之前应用。
查询优化器可能无法识别所有可以在分组操作之前应用的 HAVING 搜索条件。建议将所有这些搜索条件放在 WHERE 子句中,而不是 HAVING 子句中。

下面的示例显示了带有聚合函数的 HAVING 子句。它按产品 ID 分组 SalesOrderDetail 表中的行,并消除其平均订单数量小于/等于 5 的产品。

USE AdventureWorks;

GO

SELECT ProductID 

FROM Sales.SalesOrderDetail

GROUP BY ProductID

HAVING AVG(OrderQty) > 5

ORDER BY ProductID ;

GO

下面的示例显示了不带聚合函数的 HAVING 子句。它按名称分组 ProductModel 表中的行,并消除那些不以 Mountain 开头的名称。

USE AdventureWorks;

GO

SELECT pm.Name, AVG(ListPrice) AS 'Average List Price'

FROM Production.Product AS p

JOIN Production.ProductModel AS pm

ON p.ProductModelID = pm.ProductModelID

GROUP BY pm.Name

HAVING pm.Name LIKE 'Mountain%'

ORDER BY pm.Name ;

GO

请注意,ORDER BY 子句可用于排序 GROUP BY 子句的输出。

1、SQL中where, group by, having的用法和区别

group by,where,having 是数据库查询中最常用的几个关键字。
在工作中,时常用到,那么,当一个查询中使用了where ,group by ,
having及聚集函数时 ,执行顺序是怎么样的?为了回答这个问题,将这个三个关键字的用法整理一下。

where:数据库中常用的是where关键字,用于在初始表中筛选查询。
它是一个约束声明,用于约束数据,在返回结果集之前起作用。如下面这个例子,从user表中查询出userDepartmentId等于2的数据

select * from dbo.user where userDepartmentId=2

group by:对select查询出来的结果集按照某个字段或者表达式进行分组,
获得一组组的集合,然后从每组中取出一个指定字段或者表达式的值。
在说group by的时候,我们还需要了解聚合函数,聚合函数是SQL语言中一种特殊的函数。例如:

count(*):获取数量
sum():求和(这里要注意求和是忽略null值的,null与其他数值相加结果为null,所以可以通过ifnull(xxx,0)将null的值赋为0)
avg():求平均数
max():求最大值
min():求最小值
这些函数和其它函数的根本区别就是它们一般作用在多条记录上。

我们需要注意的是:在使用group by的SQL语句中,select中返回的字段,必须满足以下两个条件之一:

包含在group by语句的后面,作为分组的依据;
这些字段包含在聚合函数中。
从刚才的那个例子中,我们查询出每个城市,相同年龄的员工数量:

select city, count(*),age from dbo.user where departmentID=2 group by city,age

having:用于对 where 和 group by 查询出来的分组经行过滤,查出满足条件的分组结果。

它是一个过滤声明,是在查询返回结果集以后对查询结果进行的过滤操作。
所以having的使用需要注意以下几点:

having 只能用于 group by(分组统计语句中)
where 是用于在初始表中筛选查询,having 用于在 where 和 group by 结果分组中查询
having 子句中的每一个元素也必须出现在 select 列表中
having 语句可以使用聚合函数,而 where 不使用。
还是刚才的例子,我们进一步整理,查询员工数量大于20的城市和年龄段

select city, count(*),age from dbo.user where departmentID=2 group by city,age having age >40

回到开头的那个问题:当一个语句中同时含有where、group by 、having及聚集函数时,执行顺序如下:

执行 where 子句查找符合条件的数据;
使用 group by 子句对数据进行分组;对 group by 子句形成的组运行聚集函数计算每一组的值;最后用 having 子句去掉不符合条件的组。需要注意的是,

having 子句中的每一个元素也必须出现在 select 列表中。有些数据库例外,如 oracle.
having 子句和 where 子句都可以用来设定限制条件以使查询结果满足一定的条件限制。
having 子句限制的是组,而不是行。where 子句中不能使用聚集函数,而 having 子句中可以。当加上其他sql语句时,执行顺序如下:
S-F-W-G-H-O 组合

select –>where –> group by–> having–>order by

顺序是不能改变的

转载于:https://my.oschina.net/u/4000688/blog/2994286

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值