使用 HAVING 子句选择行
.M(tOa"O|E0 HAVING 子句对 GROUP BY 子句设置条件的方式与 WHERE 子句和 SELECT 语句交互的方式类似。WHERE 子句搜索条件在进行分组操作之前应用;而 HAVING 搜索条件在进行分组操作之后应用。HAVING 语法与 WHERE 语法类似,但 HAVING 可以包含聚合函数。HAVING 子句可以引用选择列表中出现的任意项。
D"BJ$VeC r9m/w9{PL0 下面的查询得到本年度截止到目前的销售额超过 $40,000 的出版商:
51Testing软件测试网L7O6HS ? USE pubs
51Testing软件测试网9d1jR&d#LZGtW(w SELECT pub_id, total = SUM(ytd_sales)
51Testing软件测试网pTX_J FROM titles
4R l{T{h8h0 GROUP BY pub_id
`&_`1P;P ?,aO0 HAVING SUM(ytd_sales) > 40000
7S2Dhj_,M0 下面是结果集:
51Testing软件测试网L4A XF/Z.d pub_id total
As%v"s'Qqx0 ------ -----------
51Testing软件测试网 g;[,D3wy"B-k 0877 44219
51Testing软件测试网T0DtEVEQ#Z6t (1 row(s) affected)
+|j%o+l&G4D
NP+[0 为了确保对每个出版商的计算中至少包含六本书,下面示例使用 HAVING COUNT(*) > 5 消除返回的总数小于六本书的出版商:
8Q0X4p8[:[W m1@"t,`~1r0 USE pubs
51Testing软件测试网 L.XP-x&Gl8d*z"s SELECT pub_id, total = SUM(ytd_sales)
9ji0h,sZf*@-Y;u0 FROM titles
4\(Z9i3P rh'Vp0 GROUP BY pub_id
51Testing软件测试网[)k IsrB`
g0P HAVING COUNT(pub_id) > 5
'qP+VzP#x0Nf0 下面是结果集:
jh#E*U)c7]%S
_3y'x&p[ _0 pub_id total
*a g0rLZR#R0 ------ -----------
:c+?`0^D-x0 0877 44219
51Testing软件测试网z${o)g[Ez+}mE 1389 24941
51Testing软件测试网7Td8}%Yim (2 row(s) affected)
kIY Sl%n(Tg F(yb1TF0 理解应用 WHERE、GROUP BY 和 HAVING 子句的正确序列对编写高效的查询代码会有所帮助:
51Testing软件测试网 CbD
fav0X:P WHERE 子句用来筛选 FROM 子句中指定的操作所产生的行。
hS(lv,BZg#K
G ~i0 GROUP BY 子句用来分组 WHERE 子句的输出。
d7IhTz-[m.B$m0 HAVING 子句用来从分组的结果中筛选行。
pZ8qgo,k#P0 对于可以在分组操作之前或之后应用的搜索条件,在 WHERE 子句中指定它们更有效。这样可以减少必须分组的行数。应当在 HAVING 子句中指定的搜索条件只是那些必须在执行分组操作之后应用的搜索条件。
51Testing软件测试网FSg!G&?R-[G-S[ Microsoft®
SQL Server™ 2000 查询优化器可处理这些条件中的大多数。如果查询优化器确定 HAVING 搜索条件可以在分组操作之前应用,那么它就会在分组之前应用。查询优化器可能无法识别所有可以在分组操作之前应用的 HAVING 搜索条件。建议将所有这些搜索条件放在 WHERE 子句中而不是 HAVING 子句中。
51Testing软件测试网]:Vy'e"U:zd 以下查询显示包含聚合函数的 HAVING 子句。该子句按类型分组 titles 表中的行,并且消除只包含一本书的组:
F2CQBy0 USE pubs
51Testing软件测试网3`(k(s;` M1S}+PH SELECT type
51Testing软件测试网r&Z Y2OFYF FROM titles
G!o2Mjj:B0 GROUP BY type
eznT.`{-Gp0 HAVING COUNT(type) > 1
pkU?9d.DU x
N1i0 下面是结果集:
51Testing软件测试网;hWuD;hD\ type
*YQ;T%Y:^hA-O}0 ------------------
51Testing软件测试网Rg,J8lEX:v4@;nG business
51Testing软件测试网3Q$sSB VSu4rw mod_cook
51Testing软件测试网V LDM8cN popular_comp
51Testing软件测试网l*Jb0rX)j)Q%o7M psychology
51Testing软件测试网;G+tlE1JTv]+N trad_cook
ZDZ-\tC`0 (5 row(s) affected)
51Testing软件测试网j)V:|P8EW6r,C| 以下是没有聚合函数的 HAVING 子句的示例。该子句按类型分组 titles 表中的行,并且消除不是以字母 p 开头的那些类型。
Q+h"Q\AY`0 USE pubs
51Testing软件测试网+Y1@B(v)b.a2E SELECT type
eq5J8kNPm9\1v K
V0 FROM titles
51Testing软件测试网,@$s-L;y&A]ma@ GROUP BY type
51Testing软件测试网 QC,?KTPY HAVING type = '%p%'
51Testing软件测试网F/r~F6n9C 下面是结果集:
+G|L2U
u0 type
)N*v
u*|E6w.\0 ------------------
8Y]3hg5y3I5I5H-SR0 popular_comp
51Testing软件测试网KH]!o"H"pq psychology
g|$}*o+x]mV]0 (2 row(s) affected)
51Testing软件测试网Hk.tx
x
ZA3pq/L 如果 HAVING 中包含多个条件,那么这些条件将通过 AND、OR 或 NOT 组合在一起。以下示例显示如何按出版商分组 titles,只包括那些标识号大于 0800、支付的总预付款已超过 $15,000 且销售书籍的平均价格小于 $20 的出版商。
|;rF]
Pg-g0 SELECT pub_id, SUM(advance) AS AmountAdvanced,
51Testing软件测试网*S
X\$x9T#Y AVG(price) AS AveragePrice
51Testing软件测试网S5[,RjWH'H FROM pubs.dbo.titles
51Testing软件测试网8I ?eC:wL WHERE pub_id > '0800'
51Testing软件测试网,B$N*J(t7s {
MM1k GROUP BY pub_id
6cqShtR
B0 HAVING SUM(advance) > 15000
bFX!_&R0 AND AVG(price) < 20
t4S)u.BQ,s$S{0 ORDER BY 可以用来为 GROUP BY 子句的输出排序。下面的示例显示使用 ORDER BY 子句以定义返回 GROUP BY 子句中的行的顺序:
MxB
z9a@0 SELECT pub_id, SUM(advance) AS AmountAdvanced,
nNRvNT.MGi0 AVG(price) AS AveragePrice
x7H+VH#{D2[l"O0 FROM pubs.dbo.titles
51Testing软件测试网,N@i
_2}D
C h WHERE pub_id > '0800'
51Testing软件测试网B'?!s
st-RmigGl AND price >= 5
1mwzaG-y8CP!M0 GROUP BY pub_id
51Testing软件测试网\Z/F'fo+i3X$[f HAVING SUM(advance) > 15000
y}` Q!U+M3Z0 AND AVG(price) < 20
0lMX:`[ q8KD
o0 ORDER BY pub_id DESC
51Testing软件测试网5O6J
eE9E0w