范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

神奇的SQL之HAVING容易被轻视的主角

  开心一刻
  一天,楼主和隔壁小男孩一起坐电梯,中途进来一位高挑的美女,她牵着一条雪白的贵宾犬
  小男孩看着这条雪白的贵宾犬,甚是喜欢,说道:阿姨,我能摸下这个狗狗吗?
  美女:叫姐姐
  小男孩低头看了下贵宾犬,虽说有点不乐意,但还是说道:阿姨,我能摸下这个姐姐吗?
  楼主想忍住,但实在是忍不住了,哈哈哈...
  初识 HAVING
  关于 SQL 中的 HAVING,相信大家都不陌生,它往往与 GROUP BY 配合使用,为聚合操作指定条件
  说到指定条件,我们最先想到的往往是 WHERE 子句,但 WHERE 子句只能指定行的条件,而不能指定组的条件(这里面有个"阶"的概念,可以查阅:神奇的 SQL 之层级 → 为什么 GROUP BY 之后不能直接引用原表中的列),因此就有了 HAVING 子句,它用来指定组的条件。我们来看个具体示例就清楚了。
  我们有 学生班级表(tbl_student_class) 以及 数据如下 : DROP TABLE IF EXISTS tbl_student_class; CREATE TABLE tbl_student_class (   id int(8) unsigned NOT NULL AUTO_INCREMENT COMMENT "自增主键",   sno varchar(12) NOT NULL COMMENT "学号",   cno varchar(5) NOT NULL COMMENT "班级号",   cname varchar(50) NOT NULL COMMENT "班级名",   PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT="学生班级表";  -- ---------------------------- -- Records of tbl_student_class -- ---------------------------- INSERT INTO tbl_student_class(sno, cno, cname) VALUES ("20190607001", "0607", "影视7班"); INSERT INTO tbl_student_class(sno, cno, cname) VALUES ("20190607002", "0607", "影视7班"); INSERT INTO tbl_student_class(sno, cno, cname) VALUES ("20190608003", "0608", "影视8班"); INSERT INTO tbl_student_class(sno, cno, cname) VALUES ("20190608004", "0608", "影视8班"); INSERT INTO tbl_student_class(sno, cno, cname) VALUES ("20190609005", "0609", "影视9班"); INSERT INTO tbl_student_class(sno, cno, cname) VALUES ("20190609006", "0609", "影视9班"); INSERT INTO tbl_student_class(sno, cno, cname) VALUES ("20190609007", "0609", "影视9班");
  我们要查询  学生人数为 3 的班级  ,这就需要用到 HAVING 了,相信大家都会写 SELECT cno, COUNT(*) nums FROM tbl_student_class GROUP BY cno HAVING COUNT(*) = 3;
  如果我们不使用 HAVING,会是什么样呢
  可以看到,除了数量等于 3 的班级之前,其他的班级也被查出来了
  我们可以简单总结下:WHERE 先过滤出行,然后 GROUP BY 对行进行分组,HAVING 再对组进行过滤,筛选出我们需要的组
  HAVING 子句的构成要素
  既然 HAVING 操作的对象是组,那么其使用的要素是有一定限制的,能够使用的要素有 3 种:  常数  、  聚合函数  和  聚合键  ,聚合键也就是 GROUP BY 子句中指定的 列名
  示例中的  HAVING    COUNT  (  *  )   =     3   , COUNT  ( *  )  是聚合函数,3 是常数,都在 3 要素之中;如果有 3 要素之外的条件,会是怎么样呢SELECT cno, COUNT(*) nums FROM tbl_student_class GROUP BY cno HAVING cname = "影视9班";
  执行如上 SQL 会失败,并提示: [Err] 1054 - Unknown column "cname" in "having clause"
  在使用 HAVING 子句时,把 GROUP BY 聚合后的结果作为 HAVING 子句的起点,会更容易理解;示例中通过 cno 进行聚合后的结果如下:
  聚合后的这个结果并没有  cname  这个列,那么通过这个列来进行条件处理,当然就报错了啦
  细心的小伙伴应该已经发现,HAVING 子句的构成要素和包含 GROUP BY 子句时的 SELECT 子句的构成要素是一样的,都是只能包含  常数  、  聚合函数  和  聚合键   HAVING 的魅力
  HAVING 子句是 SQL 里一个非常重要的功能,是理解 SQL 面向集合这一本质的关键。下面结合具体的案例,来感受下 HAVING 的魅力   是否存在缺失的编号
  tbl_student_class 表中记录的 id 是连续的( id 的起始值不一定是 1 ),我们去掉其中 3 条 DELETE FROM tbl_student_class WHERE id IN(2,5,6); SELECT * FROM tbl_student_class;
  如何判断是否有编号缺失?
  数据量少,我们一眼就能看出来,但是如果数据量上百万行了,用眼就看不出来了吧
  不绕圈子了,我就直接写了,相信大家都能看懂(记得和自己想的对比一下) SELECT "存在缺失的编号" AS gap FROM tbl_student_class HAVING COUNT(*) <> MAX(id) - MIN(id) + 1;
  上面的 SQL 语句里没有 GROUP BY 子句,此时整张表会被聚合为一组,这种情况下 HAVING 子句也是可以使用的(HAVING 不是一定要和 GROUP BY 一起使用)
  写的更严谨点,如下(没有 HAVING,不是主角,看一眼就好) -- 无论如何都有结果返回 SELECT CASE WHEN COUNT(*) = 0 THEN "表为空"     WHEN COUNT(*) <> MAX(id) - MIN(id) + 1 THEN "存在缺失的编号"     ELSE "连续" END AS gap FROM tbl_student_class;
   那如何找出缺失的编号了 ,欢迎评论区留言   求众数
  假设我们有一张表:  tbl_student_salary  ,记录着毕业生首份工作的年薪 DROP TABLE IF EXISTS tbl_student_salary; CREATE TABLE tbl_student_salary (   id int(8) unsigned NOT NULL AUTO_INCREMENT COMMENT "自增主键",   name varchar(5) NOT NULL COMMENT "姓名",   salary DECIMAL(15,2) NOT NULL COMMENT "年薪, 单位元",   PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT="毕业生年薪标";  insert into tbl_student_salary values (1,"李小龙", 1000000); insert into tbl_student_salary values (2,"李四", 50000); insert into tbl_student_salary values (3,"王五", 50000); insert into tbl_student_salary values (4,"赵六", 50000); insert into tbl_student_salary values (5,"张三", 70000); insert into tbl_student_salary values (6,"张一三", 70000); insert into tbl_student_salary values (7,"张二三", 70000); insert into tbl_student_salary values (8,"张三三", 60000); insert into tbl_student_salary values (9,"张三四", 40000); insert into tbl_student_salary values (10,"张三丰", 30000);
  平均工资达到了  149000   元,乍一看好像毕业生大多都能拿到很高的工资。然而这个数字背后却有一些玄机,因为功夫大师李小龙在这一届毕业生中,由于他出众的薪资,将大家的平均薪资拉升了一大截
  简单地求平均值有一个缺点,那就是很容易受到离群值(outlier)的影响。这种时候就必须使用更能准确反映出群体趋势的指标——众数(mode)就是其中之一
  那么如何用 SQL 语句来求众数了,我们往下看 -- 使用谓词 ALL 求众数 SELECT salary, COUNT(*) AS cnt FROM tbl_student_salary GROUP BY salary HAVING COUNT(*) >= ALL (     SELECT COUNT(*)     FROM tbl_student_salary     GROUP BY salary);
  结果如下
  ALL 谓词用于 NULL 或空集时会出现问题,我们可以用极值函数来代替;这里要求的是元素数最多的集合,因此可以用 MAX 函数 -- 使用极值函数求众数 SELECT salary, COUNT(*) AS cnt FROM tbl_student_salary GROUP BY salary HAVING COUNT(*) >= (     SELECT MAX(cnt)     FROM (         SELECT COUNT(*) AS cnt         FROM tbl_student_salary         GROUP BY salary         ) TMP     ) ;  求中位数
  当平均值不可信时,与众数一样经常被用到的另一个指标是中位数(median)。它指的是将集合中的元素按升序排列后恰好位于正中间的元素。如果集合的元素个数为偶数,则取中间两个元素的平均值作为中位数
  表  tbl_student_salary  有 10 条记录,那么  张三三,  60000   和  李四,  50000   的平均值  55000   就是中位数
  那么用 SQL,该如何求中位数呢?做法是,将集合里的元素按照大小分为上半部分和下半部分两个子集,同时让这 2 个子集共同拥有集合正中间的元素。这样,共同部分的元素的平均值就是中位数,思路如下图所示
  像这样需要根据大小关系生成子集时,就轮到非等值自连接出场了 -- 求中位数的SQL 语句:在HAVING 子句中使用非等值自连接 SELECT AVG(DISTINCT salary) FROM (     SELECT T1.salary     FROM tbl_student_salary T1, tbl_student_salary T2     GROUP BY T1.salary     -- S1 的条件     HAVING SUM(CASE WHEN T2.salary >= T1.salary THEN 1 ELSE 0 END) >= COUNT(*) / 2     -- S2 的条件     AND SUM(CASE WHEN T2.salary <= T1.salary THEN 1 ELSE 0 END) >= COUNT(*) / 2 ) TMP;
  这条 SQL 语句的要点在于比较条件  >=     COUNT  (  *  )  /  2   里的等号,加上等号并不是为了清晰地分开子集 S1 和 S2,而是为了让这 2 个子集拥有共同部分
  如果去掉等号,将条件改成  >     COUNT  (  *  )  /  2   ,那么当元素个数为偶数时,S1 和 S2 就没有共同的元素了,也就无法求出中位数了;加上等号是为了写出通用性更高的 SQL  查询不包含 NULL 的集合
  假设我们有一张学生报告提交记录表:tbl_student_submit_log DROP TABLE IF EXISTS tbl_student_submit_log; CREATE TABLE tbl_student_submit_log (   id int(8) unsigned NOT NULL AUTO_INCREMENT COMMENT "自增主键",   sno varchar(12) NOT NULL COMMENT "学号",   dept varchar(50) NOT NULL COMMENT "学院",   submit_date DATE COMMENT "提交日期",   PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT="学生报告提交记录表";  insert into tbl_student_submit_log values (1,"20200607001", "理学院", "2020-12-12"), (2,"20200607002", "理学院", "2020-12-13"), (3,"20200608001", "文学院", null), (4,"20200608002", "文学院", "2020-12-22"), (5,"20200608003", "文学院", "2020-12-22"), (6,"20200612001", "工学院", null), (7,"20200617001", "经济学院", "2020-12-23");
  学生提交报告后,  submit_date  列会被写入日期,而提交之前是 NULL
  现在我们需要从这张表里找出哪些学院的学生全部都提交了报告,这个 SQL 该怎么写?
  如果只是用  WHERE  submit_date   IS    NOT     NULL  条件进行查询,那文学院也会被包含进来,结果就不正确了
  正确的做法应该先以  dept  进行分组(GROUP BY),然后对组进行条件的过滤,SQL 如下 SELECT dept FROM tbl_student_submit_log GROUP BY dept HAVING COUNT(*) = COUNT(submit_date);
  这里其实用到了  COUNT   函数,COUNT(*) 可以用于 NULL ,而 COUNT(列名) 与其他聚合函数一样,要先排除掉 NULL 的行再进行统计
  当然,使用 CASE 表达式也可以实现同样的功能,而且更加通用 SELECT dept FROM tbl_student_submit_log GROUP BY dept HAVING COUNT(*) = SUM(     CASE WHEN submit_date IS NOT NULL THEN 1         ELSE 0 END     );其他
  不仅仅只是如上的那些场景适用于 HAVING,还有很多其他的场景也是需要用到 HAVING 的,有兴趣的可以去翻阅《SQL进阶教程》 聚合键条件的归属
  我们来看个有趣的东西,还是用表:tbl_student_class
  我们发现,聚合键所对应的条件既可以写在 HAVING 子句当中,也可以写在 WHERE 子句当中
  虽然条件分别写在 HAVING 子句和 WHERE 子句当中,但是条件的内容,以及返回的结果都完全相同,因此,很多小伙伴就会觉得两种书写方式都没问题
  单从结果来看,确实没问题,但其中有一种属于偏离了 SQL 规范的非正规用法,推荐做法是:  聚合键所对应的条件应该书写在 WHERE 子句中  ,理由有二
   语义更清晰
  WHERE 子句和 HAVING 子句的作用是不同的;前面已经说过,HAVING 子句是用来指定"组"的条件的,而"行"所对应的条件应该写在 WHERE 子句中,这样一来,写出来的 SQL 语句不但可以分清两者各自的功能,而且理解起来也更容易
   执行速度更快
  使用 COUNT 等函数对表中数据进行聚合操作时,DBMS 内部进行排序处理,而排序处理会大大增加机器的负担,从而降低处理速度;因此,尽可能减少排序的行数,可以提高处理速度
  通过 WHERE 子句指定条件时,由于排序之前就对数据进行了过滤,那么就减少了聚合操作时的需要排序的记录数量;而 HAVING 子句是在排序之后才对数据进行分组的,与在 WHERE 子句中指定条件比起来,需要排序的数量就会多得多
  另外,索引是 WHERE 根据速度优势的另一个有利支持,在 WHERE 子句指定条件所对应的列上创建索引,可以大大提高 WHERE 子句的处理速度 总结
  1、集合论
  集合论是 SQL 语言的根基,只有从集合的角度来思考,才能明白 SQL 的强大威力
  学习 HAVING 子句的用法是帮助我们顺利地忘掉面向过程语言的思考方式并理解 SQL 面向集合特性的最为有效的方法
  2、HAVING 子句的要素
  3 个要素: 常亮 、聚合函数 和 聚合键
  HAVING 大多数情况下和结合 GROUP BY 来使用,但不是一定要结合 GROUP BY 来使用
  3、SQL 的执行顺序
  WHERE 子句是指定行所对应的条件,而 HAVING 子句是指定组所对应的条件

试车报告开一台有驾驶乐趣的SUV,是怎样的体验?SportUtilityVehicle,这串英文是SUV的全称,翻译过来就是运动型多功能汽车。从这个命名就能看出来,即使受制于做工和技术尚未成熟,轻量化材料也还没有普遍运用,但初期奥迪又一潮流力作,跨界车A1Citycarver动感十足近日,外媒展出了奥迪A1Citycarver的官方效果图。奥迪A1Citycarver是一款在奥迪A1车型的基础上打造生产的车型,其采用了跨界车的造型,使得该车的整体外观更像是奥迪当我妹妹的画把别人吓到的时候,我却笑了我妹不是专业的画家,也没有去学过画画,今年也就高一她以前没事就自己在本子上画画,都是2D效果嘛,我也没咋关注后来她在手机上下载了一个可以画画的软件自己画画,没事就画,还是有许多的作今日感悟路线规划在看公司读书活动的书籍阿里铁军销售课,里面有这样一段话首先是路线规划,根据个人目标计划一天拜访的客户时,最好把客户安排在同一个区域,然后预估好当天整体的沟通时间,细化到每一家客户要第四章我快忍不住了我回到宫中,让碧玉帮我拿来那件成品,试穿了一下,扭头问罗兰本公主穿着你们南越的特色服饰可好看?罗兰对我没那么拘谨了,碧玉对她说过,公主要的是忠心,如果她足够忠心,公主会当她如自家姐有哪一瞬间你觉得你的猫能通人性?我先来谈谈我的我离家两年没回去了,都在学校。我住我外公外婆家,他们无论如何都会养一只猫,所以我们家是养猫元老级了。我们养过,黑色的猫猫,黄色的猫猫,花色的猫猫,白色的猫猫,还有麻色的猫猫等等,特底层人民的悲哀前几天刷公众号,看到这样几条消息1。试用期劳动合同法第十九条规定,劳动合同期限三个月以上不满一年的,试用期不得超过一个月劳动合同期限一年以上不满三年的,试用期不得超过二个月三年以上罗志祥吴亦凡如果这次锤不死,我觉得我还可以抢救一下吴亦凡(KrisWu,1990年11月06日),出生于广东省广州市,毕业于加拿大温斯顿爵士邱吉尔中等学校,加拿大籍华裔男演员歌手。来自网络吴亦凡曾多次在采访或者综艺上说,自己是个纯决策参考阿里钉钉首次超过微信快手电商推出减免技术服务费1迪士尼宣布将整合Hulu后者CEO辞职事件2月1日,美国流媒体视频服务Hulu宣布,迪士尼计划将Hulu更紧密地整合到集团业务运营中,兰迪弗利尔将辞去公司CEO一职。去年5月,迪政策解读一网整合重大利好但任重道远编者按2月26日,流媒体网发布的文章中国广电全国有线电视网络整合与广电5G融合发展中称中国广电全国一网蓄势待发。根据该文章我们可以对有线电视网络一网整合的最新政策作出解读。1基本原有线电视全国一张网整合再也慢不起了有线电视全国一张网整合历来如破旧老爷车一样,速度奇慢过程曲折,远远落后于市场和业界期待!这在20年前尚无大碍,反正有着相对垄断的自留地,慢点就慢点呗,只不过是多收还是少收三五斗的事
Kafka监控工具EFAK安装(Eagle)EFAK(EagleForApacheKafka)是一个简单高性能的Kafka集群监控系统,实现了监控可视化操作TopicZookeeperSQL查询告警等功能,它以前的名字叫Ka继续深挖!随着时间的沉淀,小主线逐渐清晰,教头认为市场资金介入较深的热点主要集中在汽车产业链中,从上上周开始,汽配整车等板块趋势走强,低位相关题材和个股不断被挖掘。而当前最火的细分集中在比亚Redis作为缓存服务器的配置随着redis的发展,越来越多的架构用它取代了memcached作为缓存服务器的角色,它有几个很突出的特点1。除了Hash,还提供了SortedSet,List等数据结构2。可以持半月谈丨向996说不?先疏通堵点向996说不?先疏通堵点半月谈记者陈旭阳娜996715007一串串代号在互联网频繁出现,共同指向讳莫如深的超时加班现象。为了劳动者体面工作幸福生活,3月以来,多省份开展集中整治超时不给美芯留活路?中企自研芯片下放,张召忠说得很对美国对华为等中企实施的芯片断供无疑是把双刃剑,虽然暂时对中企的发展造成了阻碍,但以出口为主的美半导体市场卖的配件也少了,业绩报表股价都出现了下滑。前不久美国传出消息,高通谷歌英特尔金海高科最新公告拟定增募资不超3。5亿元用于新能源汽车空气过滤器等项目金海高科公告,拟定增募资不超过3。5亿元,用于诸暨年产555万件新能源汽车空气过滤器研发及产业化项目珠海年产150万件新能源汽车空气过滤器研发及产业化项目和数字化管理平台建设项目。通信行业迎来业绩回暖立讯精密(SZ002475)天孚通信(SZ300394)广和通(SZ300638)宝信软件(SH600845)通信行业整体业绩增速回升,景气度持续改善。需求提升带动上市公司营收稳步传EA积极寻求卖身曾和迪士尼苹果亚马逊等谈判游戏行业现已进入了一个合并时代,大型发行商动视暴雪,B社,开发商Bungie等都被收购,那么作为世界上排名一直靠前的发行商EA呢?在一个人人有价的时代,关于EA的传闻倒是出奇地少。江苏省海归人才积极投身创新创业浪潮在科技报国服务人民中成就出彩人生5月21日,南京江北新区研创园,矽典微CEO徐鸿涛仍在公司会议室里进行着团队例会分享。成立不到3年,矽典微已开发出数款传感器芯片产品,在业内崭露头角,目前企业发展正处于快速上升期。每年遴选培育1000名数字经济卓越工程师,江苏人社出台服务数字经济发展20条现代快报讯(记者徐苏宁)每年遴选培育1000名数字经济卓越工程师聚焦重大创新平台建立事业编制周转池大力实施数字技能提升行动提升数字人社政务服务。。5月23日,现代快报记者获悉,江苏手写一个操作系统01在真正打造操作系统前,有一条必经之路你知道程序是如何运行的吗?计算机硬件是无法直接运行C语言文本程序代码的,需要C语言编译器,把这个代码编译成具体硬件平台的二进制代码。再由具体操作