记录黑客技术中优秀的内容,传播黑客文化,分享黑客技术精华

SQL 查询语句先执行 SELECT?兄弟你认真的么?

2020-08-19 22:27



文章来自:https://blog.csdn.net/qq_39390545/article/details/105893049


商务合作: 请加微信 2230304070









IT技术交流群

我们在学习技术中单枪匹马,还不如一次短短的交流,你可以在别人吸取各种学习经验,学习方法以及学习技巧。所以,学习与交流少不了一个圈子,提升你的学习技能,请点击加技术群:IT技术交流微信群



精选文章正文


SQL 查询的执行顺序是怎样呢?

好像这个问题应该很好回答,毕竟自己已经写了无数个 SQL 查询了,有一些还很复杂的。

但事实是,这个问题小编很难确切地说出它的顺序是怎样的。


言归正传,SELECT语句的完整语法如下:

SELECT
DISTINCT <select_list>
FROM <left_table>
<join_type> JOIN <right_table>
ON <join_condition>
WHERE <where_condition>
GROUP BY <group_by_list>
HAVING <having_condition>
ORDER BY <order_by_condition>
LIMIT <limit_number>


然而其执行顺序却是:

FROM
<表名> # 笛卡尔积
ON
<筛选条件> # 对笛卡尔积的虚表进行筛选
JOIN <join, left join, right join...>
<join表> # 指定join,用于添加数据到on之后的虚表中,例如left join会将左表的剩余数据添加到虚表中
WHERE
<where条件> # 对上述虚表进行筛选
GROUP BY
<分组条件> # 分组
<SUM()等聚合函数> # 用于having子句进行判断,在书写上这类聚合函数是写在having判断里面的
HAVING
<分组筛选> # 对分组后的结果进行聚合筛选
SELECT
<返回数据列表> # 返回的单列必须在group by子句中,聚合函数除外
DISTINCT
# 数据除重
ORDER BY
<排序条件> # 排序
LIMIT
<行数限制>


其实,引擎在执行上述每一步时,都会在内存中形成一张虚拟表,然后对虚拟表进行后续操作,并释放没用的虚拟表的内存,以此类推。


具体解释:(注:下面“VT”表示 → 虚拟表 virtual )

from:select * from table_1, table_2; 与 select * from table_1 join table_2; 的结果一致,都是表示求笛卡尔积;用于直接计算两个表笛卡尔积,得到虚拟表VT1,这是所有select语句最先执行的操作,其他操作时在这个表上进行的,也就是from操作所完成的内容


on: 从VT1表中筛选符合条件的数据,形成VT2表;


    join: 将该 join 类型的数据补充到VT2表中,例如 left join 会将左表的剩余数据添加到虚表VT2中,形成VT3表;若表的数量大于2,则会重复1-3


    where: 执行筛选,(不能使用聚合函数)得到VT4表;


    group by: 对VT4表进行分组,得到VT5表;其后处理的语句,如select,having,所用到的列必须包含在group by条件中,没有出现的需要用聚合函数;


    having: 筛选分组后的数据,得到VT6表;


    select: 返回列得到VT7表;


    distinct: 用于去重得到VT8表;


    order by: 用于排序得到VT9表;


    limit: 返回需要的行数,得到VT10;


    需要注意的是:

    • group by条件中,每个列必须是有效列,不能是聚合函数;
    • null值也会作为一个分组返回;
    • 除了聚合函数,select子句中的列必须在group by条件中;

     

    上述内容让我们知道一个查询会返回什么,同时,也回答了以下这些问题:

    • 可以在 GRROUP BY 之后使用 WHERE 吗?(不行,GROUP BY 是在 WHERE 之后!)
    • 可以对窗口函数返回的结果进行过滤吗?(不行,窗口函数是 SELECT 语句里,而 SELECT 是在 WHERE 和 GROUP BY 之后)
    • 可以基于 GROUP BY 里的东西进行 ORDER BY 吗?(可以,ORDER BY 基本上是在最后执行的,所以可以基于任何东西进行 ORDER BY)
    • LIMIT 是在什么时候执行?(在最后!)



    但是,数据库引擎并不一定严格按照这个顺序执行 SQL 查询,因为为了更快地执行查询,它们会做出一些优化,这些问题会在下方进行解释↓↓↓。



    SQL中的别名会影响SQL执行顺序么?


    如下方SQL所示:

    SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*)
    FROM table
    GROUP BY full_name


    从这个语句来看,好像 GROUP BY 是在 SELECT 之后执行的,因为它引用了 SELECT 中的一个别名。但实际上不一定要这样,数据库引擎会把查询重写成这样↓↓↓:

    SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*)
    FROM table
    GROUP BY CONCAT(first_name, ' ', last_name)


    所以,这样 GROUP BY 仍然先执行。

    另外,数据库引擎还会做一系列检查,确保 SELECT 和 GROUP BY 中的东西是有效的,所以会在生成执行计划之前对查询做一次整体检查。

     


    数据库很可能不按正常顺序执行查询(优化)

    在实际当中,数据库不一定会按照 JOIN、WHERE、GROUP BY 的顺序来执行查询,因为它们会进行一系列优化,把执行顺序打乱,从而让查询执行得更快,只要不改变查询结果。 


    这个查询说明了为什么需要以不同的顺序执行查询:

    SELECT * FROM
    dept d LEFT JOIN student s ON d.student_id = s.id
    WHERE s.name = '陈哈哈'


    如果只需要找出名字叫“陈哈哈”的学生信息,那就没必要对两张表的所有数据执行左连接,在连接之前先进行过滤,这样查询会快得多,而且对于这个查询来说,先执行过滤并不会改变查询结果。



    以上是本文的全部内容,希望对大家的学习有帮助,也希望大家多多支持php自学中心 


    知识来源: https://mp.weixin.qq.com/s?__biz=MzIxMDA0OTcxNA==&mid=2654260192&idx=1&sn=38542be452d54a37b7753a4b315aefa4&chksm=8caae43dbbdd6d2b0cc3fb2bc03e2baa4454ee2abbf1852a0c779d2cd873d3c8b07f4a5baf33&scene=126&

    阅读:24871 | 评论:0 | 标签:SQL 执行

    想收藏或者和大家分享这篇好文章→复制链接地址

    “SQL 查询语句先执行 SELECT?兄弟你认真的么?”共有0条留言

    发表评论

    姓名:

    邮箱:

    网址:

    验证码:

    公告

    ❤人人都能成为掌握黑客技术的英雄❤

    ADS

    标签云