使用 HAVING 子句选择行

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

下面的查询得到本年度截止到目前的销售额超过 $40,000 的出版商:

USE pubs SELECT pub_id, total = SUM(ytd_sales) FROM titles GROUP BY
pub_id HAVING SUM(ytd_sales) > 40000

下面是结果集:

pub_id total


0877 44219

(1 row(s) affected)

USE pubs SELECT pub_id, total = SUM(ytd_sales) FROM titles GROUP BY
pub_id HAVING COUNT(*) > 5

下面是结果集:

pub_id total


0877 44219

1389 24941

(2 row(s) affected)

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

  • WHERE 子句用来筛选 FROM 子句中指定的操作所产生的行。
  • GROUP BY 子句用来分组 WHERE 子句的输出。
  • HAVING 子句用来从分组的结果中筛选行。

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

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

以下查询显示包含聚合函数的 HAVING 子句。该子句按类型分组 titles
表中的行,并且消除只包含一本书的组:

USE pubs SELECT type FROM titles GROUP BY type HAVING COUNT(*) > 1

下面是结果集:

type


business

mod_cook

popular_comp

psychology

trad_cook

(5 row(s) affected)

以下是没有聚合函数的 HAVING 子句的示例。该子句按类型分组 titles
表中的行,并且消除不是以字母 p 开头的那些类型。

USE pubs SELECT type FROM titles GROUP BY type HAVING type LIKE ‘p%’

下面是结果集:

type


popular_comp

psychology

(2 row(s) affected)

如果 HAVING 中包含多个条件,那么这些条件将通过 AND、OR 或 NOT
组合在一起。以下示例显示如何按出版商分组 titles,只包括那些标识号大于
0800、支付的总预付款已超过 $15,000 且销售书籍的平均价格小于 $20
的出版商。

SELECT pub_id, SUM(advance) AS AmountAdvanced, AVG(price) AS
AveragePrice FROM pubs.dbo.titles WHERE pub_id > ‘0800’ GROUP BY
pub_id HAVING SUM(advance) > $15000 AND AVG(price) < $20

ORDER BY 可以用来为 GROUP BY 子句的输出排序。下面的示例显示使用 ORDER BY
子句以定义返回 GROUP BY 子句中的行的顺序:

SELECT pub_id, SUM(advance) AS AmountAdvanced, AVG(price) AS
AveragePrice FROM pubs.dbo.titles WHERE pub_id > ‘0800’ AND price
>= $5 GROUP BY pub_id HAVING SUM(advance) > $15000 AND AVG(price)
< $20 ORDER BY pub_id DESC

相关文章