为了最简单地说明问题,我特地设计了一张这样的表。

  

一、GROUP BY单值规则

  规则1:单值规则,跟在SELECT后面的列表,对于每个分组来说,必须返回且仅仅返回一个值。

  典型的表现就是跟在SELECT后面的列,如果没有使用聚合函数,必须出现在GROUP BY子句后面。

  如下面这个查询报错:

  

  因为对于按照部门分组之后,技术部分组有3个编号,销售部分组有2个编号,你让数据库显示哪个呢?

  如果假设你使用聚合函数COUNT(编号)之后,对于每个部门分组,就只有一个值 - 该部门下的人数:

  

  下面来实战下,我们希望查询出每个部门,最高工资的那个人的姓名,部门,工资。

  

  Shit,出师不利。第一次实战就错误了,我们来分析下。

  很明显,上面的姓名列是不符合单值规则的。我们的一厢情愿想法是,MAX(工资)之后,SQL Server就能自动帮我们返回不符合单值规则的'姓名'。但是很遗憾,SQL Server并没有这么做。理由如下:

  1.   如果两个人的工资相同,那么应该将哪个人的姓名返回?
  2.   如果我们使用的不是MAX()聚合函数,而是SUM、AVG等聚合函数(没有与之匹配的工资),那么姓名返回哪个?
  3.   如果在查询语句中使用了两个聚合函数,如MAX(),MIN()。那么应该返回的是MAX工资的姓名,还是MIN工资的姓名呢?

  综上所述,数据库是不可能能够根据我们输入的一个聚合函数,就帮助我们判断并显示出不符合单值规则的列的。

  对于MYSQL来说,当有这种不符合单值规则的列时,默认是返回这一组结果的第一条记录。而SQLite是返回最后一条。

  因此,对于以上查询,我们要另寻解决方案。

  解决方案1:关联子查询

SELECT 姓名,部门,工资 FROM 工资表 AS T1
WHERE NOT EXISTS (SELECT NULL FROM 工资表 AS T2 WHERE T1.部门 = T2.部门 AND T2.工资 > T1.工资)

  输出如下:

  

  完全符合要求。对于上面的关联子查询,可以理解为:

  遍历工资表的所有记录,查找不存在比当前记录部门相同且工资还大的记录。

  虽然,关联子查询的语法非常简单,但是性能并不好。因为对于每一条记录,都要执行一次子查询。

  解决方案2:衍生表

   使用衍生表的思路是,先执行一个子查询,得到一个临时结果集,然后用临时结果集和原表进行INNER JOIN操作。就能得到最高工资的人的信息。

  

  刚写出这个SQL语句时,觉得非常妙,理解了之后觉得非常妙。

SELECT 姓名,T1.部门,工资 FROM 工资表 AS T1 INNER JOIN
(SELECT 部门,MAX(工资) AS 最高 FROM 工资表    --执行查询,先记录两个字段 部门-最高工资GROUP BY 部门
) AS T2        --衍生表T2
ON T1.部门 = T2.部门 AND 工资 = 最高

  衍生表的方式性能优于关联子查询,因为衍生表的方式只执行了一次子查询。但是它需要一张临时表来存储临时记录。因此,这个方案也并不是最佳的解决方案。

  解决方案3:使用JOIN + IS NULL

  这是一个更妙的解决方案,当我们用一个外联结去匹配记录时,当匹配的记录不存在,就会用NULL来代替相应的列。

  我们先来看一条非常简答的SQL语句:

  

  从中你看到了什么?当T2表中,不存在比T1表中工资高的记录时就返回NULL。

  那么,那么,那么一个IS NULL是不是就解决问题了呢?

  

  好妙,好妙的方法,让人拍案叫绝的使用了OUTER JOIN。

  JOIN解决方案适用于针对大量数据查询并且可伸缩比较时。它总是能比基于子查询的解决方案更好地适应数据量的变量。

  解决方案4:对额外的列使用聚合函数

  我们知道,GROUP BY时,SELECT列表必须返回的是单值,那么我们可不可以通过使用聚合函数,让这个列返回单值呢?答案是可以的。

  

  其实,返回的数据是有问题的,当工资相同时,它就返回按姓名从大到小排列的第一个姓名。也就是说,当工资相同时,它只能够返回一条记录。

  我们将聚合函数换成MIN看看。

  

  解决方案5:Row_Number() + OVER

  WITH B AS(SELECT row_number() OVER(PARTITION BY Name ORDER BY CreateTime) AS part ,Score, Name, CreateTimeFROM xxx)SELECT * FROM B WHERE Part = 1

  输出如下:

  

二、HAVING的理解

  WHERE与HAVING的区别:

  •   WHERE(分组前过滤):WHERE不能对聚合函数列进行过滤,因为执行WHERE的时候,分组尚未执行,聚合函数也未执行。
  •   HAVING(分组后过滤):主要用于对聚合函数列进行过滤,因为HAVING实在分组之后执行的。HAVING子句只能配合GROUP BY子句使用。没有GROUP BY子句时不能使用HAVING。

  错误使用WHERE的示例:

  

  正确使用WHERE与HAVING的示例:

  

转载于:https://www.cnblogs.com/zxtceq/p/7160402.html

查询反模式 - GroupBy、HAVING的理解相关推荐

  1. 查询反模式 - 隐式的列

    一.减少输入 程序员都喜欢使用通配符,如: SELECT * FROM Person 又或者省略字段名: INSERT INTO Person VALUES('10','张飞'...) 二.捷径会让你 ...

  2. [译] How to NOT React:React 中常见的反模式与陷阱

    原文地址:How to NOT React: Common Anti-Patterns and Gotchas in React 原文作者:NeONBRAND 译文出自:掘金翻译计划 本文永久链接:g ...

  3. 仓储模式到底是不是反模式?

    [导读]仓储模式我们已耳熟能详,但当我们将其进行应用时,真的是那么得心应手吗?确定是解放了生产力吗?这到底是怎样的一个存在,确定不是反模式? 一篇详文我们探讨仓储模式,这里仅我个人的思考,若有更深刻的 ...

  4. 有效的ejb 和 反模式的那些事 热土豆 金锤子 等

    这是原文翻译过来的 原文出处: Effective EJB: Make EJBs Work For You Java开发正处于一个十字路口.开放的标准已经为Java平台和语言带来了很多益处,但它们也带 ...

  5. 都在说微服务,那么微服务的反模式和陷阱是什么(二)

    译者:程超 译文:http://www.jianshu.com/p/c76f7f234a31 上篇:<都在说微服务,那么微服务的反模式和陷阱是什么(一)> 六.无因的开发者陷阱 名字来自詹 ...

  6. SQL反模式笔记17——用一条sql解决复杂问题

    目标:检查sql查询次数 反模式:试图用一条sql解决复杂问题 结果是:性能很低,而且往往得到了一个笛卡尔积. 解决方案:分而治之 用多个sql得到数据,再进行整合.或者union多个sql的结果. ...

  7. 反模式:神仙大类和黄金大锤

    数学中有正数和负数 物理学有『物质』和『反物质』的存在 武侠小说中有九阳神功也有九阴真经 生活中有婚姻也有出轨 ...... 事物总是充满这种相互矛盾而统一的有趣现象. 对于GoF提出的23种设计模式 ...

  8. 一个设计反模式——究竟什么是轮子理论

    发这篇文章是从看到一篇<也谈"轮子理论">引起的,作者的观点是说,如果真的像轮子理论一样,那么这个世界上就没有了新技术的诞生.那是不是轮子理论本身的局限性呢?我个人有着 ...

  9. SQL反模式笔记7——多列属性

    目标:存储多值属性 反模式:创建多个列.比如产品主图,开始需求是,每个产品都是3张图,但随着时间的推移,可能就不止3张了. 1.查询:多个列的话,查询时可能不得不用IN,或者多个OR 2.添加.删除. ...

最新文章

  1. 分享7个我常去的国外AjaxJquery网站
  2. nginx反向代理编译异常
  3. C语言中嵌入正则表达式
  4. 《Spring Cloud Netflix官方文档》2. 服务发现:Eureka服务器
  5. cvtcolor python opencv_二值分析 | OpenCV + skimage如何提取中心线
  6. 前端基础-HTML的的标签详解
  7. 前端学习(2482):关于接口的调错
  8. jdbc mysql myeclipse_关于JDBC连接MySQL的问题,我一直解决不了(Myeclipse 环境下)
  9. 网页web前端学习技巧
  10. [C++] Vector对象的合法定义
  11. 人工智能与机器学习大牛们的blog
  12. 带修改离线主席树 + 树状数组 ZOJ - 2112【Dynamic Rankings】
  13. Buses and People CodeForces 160E 三维偏序+线段树
  14. C语言中的strcmp函数的作用是什么,c语言strcmp函数用法是什么?
  15. 期刊论文发表的格式详细介绍
  16. BH1750FVI光强度传感器及其STM32驱动程序
  17. matlab解算平差实例,MATLAB软件在测量平差解算中的应用
  18. 不到30秒接满一壶水,352S100 极速净水器体验
  19. STM32Cube STM32L053配置GPIO达到最低功耗详解含测量实际电流值
  20. Centos7:solr伪集群(SolrCloud)搭建

热门文章

  1. C语言程序设计之回调函数实现方法
  2. 2021考研时间公布 2020年12月26日至27日进行初试
  3. Python 3.8.0 正式发布,主要更新内容介绍
  4. MIT发布“全球最快AutoML”,刷新DARPA比赛成绩
  5. 深度学习系列之CNN核心内容
  6. 谷歌开发者机器学习词汇表:纵览机器学习基本词汇与概念
  7. 最清晰的讲解各种梯度下降法原理与Dropout
  8. Fedora 30将获得Bash 5.0,淘汰Yum推迟到Fedora 31
  9. 宇宙第一 IDE Visual Studio 2019 正式发布
  10. 清华计算机知识工程怎么样,张民(muslv)清华大学计算机系知识工程组 硕士清华大学.ppt...