sql having 多条件_一条SQL语句的千回百转

本文通过一条SQL语句的执行过程,详细解析了MySQL中FROM, ON, JOIN, WHERE, GROUP BY, HAVING的执行顺序。强调了在理解SQL语法和执行顺序上的差异对于正确编写SQL的重要性。文中还提到MySQL对GROUP BY和HAVING的扩展,允许使用SELECT字段别名和非列表表达式。" 125964505,11350292,C++实现狼人杀游戏,"['C++', '游戏开发']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点击关注上方“SQL数据库开发”,

设为“置顶或星标”,第一时间送达干货

SQL从本质上来说,它是一种结构化查询语言,是用来数据库之间的通信的编程语言。作为一名Java程序员,我们从Java角度来看,SQL语言相当于Java接口,而数据库是实现这个接口的实现类,SQL语句则是实现类的方法!!。从这里我们就可以理解了,每个数据库都有着自己独特的规则,但大体上是遵循SQL标准。

SQL 语句有一个让大部分人都感到困惑的地方,就是我写的 SQL 语句的跟我预想要的结果不一样。在这里,我们就以 Mysql 数据库为例,对一条 SQL 语句的执行顺序进行分析。

接下来再走一步,让我们看看一条 SQL 语句的前世今生。

首先看一下示例语句

8d0e5f5c419f1e752e284cdf6addf185.png

它的执行顺序是这样的

e49a29af7d5d4b5a0074910c4b6ad9a3.png

准备数据

我们会先准备一些数据,即创建 classes、student 表,并插入测试数据, SQL语句如下:

e014a9fc3204450d38d55ca4d1abc512.png

ec91f0508a454d0d234393ead40d059e.png

OK,有了数据之后,我们就可以来看看 SQL 语句在 MySQL 中执行过程了,SQL 语句如下:

816c7af4182cc91246e874e59464ac85.png

SQL执行之旅

可能你现在还对 Mysql 语句的执行顺序一知半解,没关系,下来我将按 SQL 执行的顺序详细介绍每个关键字的作用,以及注意的地方。

1、FROM:首先,是从 From 开始的,对FROM子句中的前两个表执行笛卡尔积(交叉联接),生成虚拟表VT1。

2c96d33886aa6ec2e58d5e36c2e44582.png

2、ON:对VT1应用ON筛选器,只有那些使为真才被插入到VT2。ON不能单独,在这里你可以把ON理解为WHERE。

b3833e9e2731e8ad4e6d148c5b22ed2b.png

3、JOIN:如果指定了OUTER JOIN(相对于CROSS JOIN或INNER JOIN),保留表(主表)中不符合ON条件匹配的行将作为外部行添加到VT2,生成VT3。如果FROM子句超过两个表,上一个联接生成的结果表会和下一个表重复执行步骤1到步骤3,直到处理完所有的表的关联。

199435d9af0209589f1cca80a343a48e.png

4、WHERE:对VT3应用WHERE筛选器,只有为true的行才插入VT4。

87f32bd4fe128e0672ef21d1cda366d5.png

5、GROUP BY:按GROUP BY子句中的列列表对VT4中的行进行分组,生成VT5。

272abb2f464e26dbab5dbbc8083bb803.png

在这里会有一个奇怪的现象,MySQL执行顺序GROUP BY -> HAVING -> SELECT,从顺序看SELECL在GROUP BY之后,GROUP BY 应该不可以使用SELECT字段别名,但是在GROUP BY却可以使用SELECT字段别名,主要原因MySQL扩展了标准SQL,允许GROUP BY子句使用的SELECT子句中的别名以及和非列表表达式等标准, 并认为语句是有效的。从MySQL 5.7.5开始,默认SQL mode模式包括 ONLY_FULL_GROUP_BY。(在5.7.5之前,MySQL不检测功能依赖性,ONLY_FULL_GROUP_BY默认情况下不启用。

6、HAVING :对VT5应用HAVING筛选器,只有为true的组插入到VT6。

ca8c5f36d12d1f36115d2e31023202b6.png

HAVING同GROUP BY一样,MySQL拓展SQL标准以允许HAVING可以使用别名和非列表表达式。

7、SELECT:将VT6每一组数据执行select xx,有几组就执行几次,产生VT7。

64b40b1fa554951e7bd101a9e2fd6705.png

这里有一点要注意,当SQL mode 模式ONLY_FULL_GROUP_BY不开启,不会强制SELECT指定的字段必须属于GROUP BY后的条件。若符合条件的字段有多个,则只显示第一次出现的字段。虽然这种查询在语法上通过了,但结果并没有什么意义,因为其他字段并非需要的准确值。所以最好SELECT语句指定的字段必须是“分组依据字段”。

8、ORDER BY:将VT7中的行按ORDER BY子句中的列列表顺序,ORDER BY只能选择SELECT的字段

1f4acd4cfad79306cd70be92533556c8.png

9、LIMIT:从VT7的开始处选择指定数量或比例的行,生成表VT8,并返回给调用者。

8e52f2c0a4ef98d7eb6cd2b784f4f17a.png

OK,到这里就执行结束了。我们可以发现,SQL 语句的语法顺序和执行顺序并不一致,如果你已经可以清醒知道它们之间差异,你就可以看出为什么以前写的SQL总是和我们预想的不一致。你看,哪怕只有一条小小的 SQL 语句都有这么多门道,只有不断专研探究,我们才可以真正掌握这一门技术。

这里多提一下,在SQL语法有几点要特别注意,SELECT虽然在GROUP BY和HAVING 之后,但是如果SQL mode模式 ONLY_FULL_GROUP_BY不开启,GROUP BY和HAVING是允许使用SELECT的字段,而且也不会强制SELECT指定的字段必须属于GROUP BY后的条件。至此SQL的解析之旅就结束了,最后用一张图总结一下今天的内容:

db4cbfdcc81eaf70289cb621bd4459e1.png

作者:Feng

来源:哈儿的数据城堡

——End——

后台回复关键字:1024,获取一份精心整理的技术干货后台回复关键字:进群,带你进入高手如云的交流群。推荐阅读
  • SQL 语法速成手册

  • 可怕,如果张东升是个程序员……

  • 我只会SQL,到底能不能找到好工作呢?
  • Oracle常用函数整理
  • MySQL常用函数整理
这是一个能学到技术的公众号,欢迎关注6f62c0a61bd0d67f06a0d68791c52f2d.png点击「」了解SQL训练营
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值