第五十章 SQL命令 HAVING(一)

第五十章 SQL命令 HAVING(一)

对一组数据值指定一个或多个限制性条件的SELECT子句。

大纲

SELECT field
FROM table
GROUP BY field
HAVING condition-expression

SELECT aggregatefunc(field %AFTERHAVING)
FROM table
[GROUP BY field]
HAVING condition-expression

参数

  • condition-expression - 由一个或多个布尔谓词组成的表达式,用于控制要检索哪些数据值。

描述

可选的HAVING子句出现在FROM子句、可选的WHEREGROUP BY子句之后,可选的ORDER BY子句之前。

SELECT语句的HAVING子句限定或取消查询选择中的特定行。符合条件的行是条件表达式为真的行。条件表达式是一系列逻辑测试(谓词),它们可以通过ANDOR逻辑运算符链接起来。

HAVING子句类似于WHERE子句,它可以在组上操作,而不是在整个数据集上操作。因此,在大多数情况下,HAVING子句要么与使用%AFTERHAVING关键字的聚合函数一起使用,要么与GROUP BY子句结合使用,或者两者兼而有之。

HAVING子句条件表达式还可以指定聚合函数。WHERE子句条件表达式不能指定聚合函数。下面的示例显示了这一点:

SELECT Name,Age,AVG(Age) AS AvgAge
FROM Sample.Person
HAVING Age > AVG(Age)
ORDER BY Age
image.png

HAVING子句通常用于将子群体的聚合与整个群体的聚合进行比较。

指定字段

HAVING子句条件表达式或%AFTERHAVING关键字表达式中指定的字段必须指定为字段名或聚合函数。不能按列号指定字段或聚合函数。不能按列别名指定字段或聚合函数;尝试这样做会生成SQLCODE-29错误。但是,可以使用子查询定义列别名,然后在HAVING子句中使用该别名。例如:

SELECT Y AS TeenYear,AVG(Y %AFTERHAVING) AS AvgTeenAge FROM 
      (SELECT Age AS Y FROM Sample.Person WHERE Age<20) 
HAVING Y > 12 ORDER BY Y
image.png

选择项列表中的聚合函数

HAVING子句选择要返回的行。默认情况下,此行选择不确定选择项列表中的聚合函数的值。这是因为HAVING子句在SELECT-ITEM列表中的聚合函数之后进行解析。

在下面的示例中,只返回Age > 65的行。但AVG(年龄)是基于所有行计算的,而不仅仅是HAVING子句选择的行:

SELECT Name,Age,AVG(Age) AS AvgAge FROM Sample.Person
HAVING Age > 65
 ORDER BY Age
image.png

将它与WHERE子句进行比较,WHERE子句选择返回哪些行,以及在select-item列表的聚合函数中包含哪些行值:

SELECT Name,Age,AVG(Age) AS AvgAge FROM Sample.Person
WHERE Age > 65
ORDER BY Age

HAVING子句可以用于只返回聚合值的查询:

  • 聚合阈值:HAVING子句使用聚合阈值来确定是返回1行(包含查询聚合值)还是0行。
    因此,可以使用HAVING子句只在达到聚合阈值时返回聚合计算。
    下面的示例仅在表中至少有100行时返回表中所有行的Age值的平均值。
    如果小于100行,所有行的Age值的平均值可能被认为没有意义,因此不应该返回:
SELECT AVG(Age) FROM Sample.Person HAVING COUNT(*)>99
image.png
  • 多行:带有聚合函数且没有GROUP BY子句的HAVING子句返回满足HAVING子句条件的行数。
    聚合函数值是根据表中的所有行计算的:
SELECT AVG(Age) FROM Sample.Person HAVING %ID<10
image.png

这与带有聚合函数的WHERE子句相反,后者返回一行。
聚合函数值是根据满足WHERE子句条件的行计算的:

SELECT AVG(Age) FROM Sample.Person HAVING %ID<10
image.png

%AFTERHAVING

%AFTERHAVING关键字可以与选择项列表中的聚合函数一起使用,以指定在应用HAVING子句条件之后执行聚合操作。

SELECT Name,Age,AVG(Age) AS AvgAge,
 AVG(Age %AFTERHAVING) AS AvgMiddleAge
 FROM Sample.Person
 HAVING Age > 40 AND Age < 65
 ORDER BY Age
image.png

只有满足以下两个条件时,%AFTERHAVING关键字才会给出有意义的结果:

  • 选择项列表必须至少包含一个非聚合字段引用的项。
    这个字段引用可以是FROM子句中指定的任何表中的任何字段、使用隐式连接(箭头语法)引用的字段、%ID别名或星号(*)。
  • HAVING子句条件必须应用至少一个非聚合条件。
    因此,有HAVING Age>50, HAVING Age>AVG(Age), or HAVING Age>50 AND MAX(Age)>75是有效的条件,但有HAVING Age>50 OR MAX(Age)>75不是有效条件。

下面的示例使用带有GROUP BY子句的HAVING子句返回状态平均年龄,以及大于表中所有行平均年龄的人的状态平均年龄。
它还使用子查询返回表中所有行的平均年龄:

SELECT Home_State,(SELECT AVG(Age) FROM Sample.Person) AS AvgAgeAllRecs,
       AVG(Age) AS AvgAgeByState,AVG(Age %AFTERHAVING) AS AvgOlderByState 
FROM Sample.Person
GROUP BY Home_State
HAVING Age > AVG(Age)
ORDER BY Home_State
image.png

逻辑谓词

SQL谓词可分为以下几类:

  • Equality Comparison谓词
  • BETWEEN谓语
  • In%INLIST谓词
  • %STARTSWITH谓词
  • 包含运算符([)
  • FOR SOME谓词
  • NULL 谓词
  • EXISTS 谓词
  • LIKE, %MATCHES, and %PATTERN 谓词
  • %INSET and %FIND 谓词

注意:不能在HAVING子句中使用FOR SOME %ELEMENT集合谓词。此谓词只能在WHERE子句中使用。

谓词区分大小写

谓词使用为字段定义的排序规则类型。默认情况下,字符串数据类型字段使用SQLUPPER排序规则定义,该排序规则不区分大小写。

%INLISTCONTAINS运算符([)、%Matches%%PATTERN谓词不使用字段的默认排序规则。它们总是使用精确排序,这是区分大小写的。

两个文字字符串的谓词比较始终区分大小写。

谓词条件和%NOINDEX

可以使用%NOINDEX关键字作为谓词条件的前缀,以防止查询优化器在该条件上使用索引。
这在指定绝大多数行都满足的范围条件时非常有用。
例如,HAVING %NOINDEX Age >= 1

相等比较谓词

以下是可用的比较谓词:

谓词 操作
= 相等
<> 不相等
!= 不相等
> 大于
< 小于
>= 大于等于
<= 小雨等于

以下示例使用比较谓词。它为小于21岁的每个年龄返回一条记录:

SELECT Name, Age FROM Sample.Person
GROUP BY Age
HAVING Age < 21
ORDER BY Age
image.png

请注意,SQL根据排序规则(值的排序顺序)定义比较操作。如果两个值以完全相同的方式排序,则它们相等。如果一个值在第二个值之后排序,则该值大于另一个值。字符串数据类型字段排序规则基于字段的默认排序规则。默认情况下,它不区分大小写。因此,两个字符串字段值的比较或字符串字段值与字符串文字的比较(默认情况下)不区分大小写。例如,如果Home_State字段值是由两个字母组成的大写字符串:

Expression Value
'MA' = Home_State TRUE for values MA.
'ma' = Home_State TRUE for values MA.
'VA' < Home_State TRUE for values VT, WA, WI, WV, WY.
'ar' >= Home_State TRUE for values AK, AL, AR.

但是请注意,两个文字字符串的比较区分大小写:其中'ma'='MA'始终为false

BETWEEN谓语

这等效于大于或等于且小于或等于的配对。下面的示例使用BETWEEN谓词。它为1835岁(包括1835岁)的每个年龄返回一条记录:

SELECT Name, Age FROM Sample.Person
GROUP BY Age
HAVING Age BETWEEN 18 AND 35
ORDER BY Age
image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容