sql 查询语句执行顺序

了解 sql 的执行顺序是很必要的,执行顺序不同可能查询到的结果最后也会不一样。

select 语句的完整语法如下:

SELECT
   DISTINCT < select_field >  
FROM
  < left_table >  < join_type >
  JOIN < right_table >  ON < join_condition >  
WHERE
  < where_condition >  
GROUP BY
  < group_by_field >  
HAVING
  < having_condition >  
ORDER BY
  < order_by_field >  
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
<行数限制>

这些步骤执行时,每个步骤都会产生一个虚拟表,该虚拟表被用作下一个步骤的输入。这些虚拟表对调用者(客户端应用程序或者外部查询)不可用。只是最后一步生成的表才会返回给调用者。如果没有在查询中指定某一子句,将跳过相应的步骤。


SELECT 各个阶段分别干了什么:

1. FROM 阶段

FROM 阶段标识出查询的来源表,并处理表运算符。在涉及到联接运算的查询中(各种 JOIN),主要有以下几个步骤:

  • 求笛卡尔积。不论是什么类型的联接运算,首先都是执行交叉连接(CROSS JOIN),求笛卡儿积(Cartesian product),生成虚拟表 VT1-J1。

  • ON 筛选器。  这个阶段对上个步骤生成的 VT1-J1 进行筛选,根据 ON 子句中出现的谓词进行筛选,让谓词取值为 true 的行通过了考验,插入到 VT1-J2。

  • 添加外部行。如果指定了 OUTER JOIN,如 LEFT OUTERJOIN、RIGHT OUTER JOIN),还需要将 VT1-J2 中没有找到匹配的行,作为外部行添加到 VT1-J2 中,生成 VT1-J3。如果 FROM 子句包含两个以上表,则对上一个连接生成的结果表 VT1-J3 和下一个表重复依次执行 3 个步骤,直到处理完所有的表为止。

经过以上步骤,FROM 阶段就完成了。


2. WHERE 阶段

WHERE 阶段是根据 <where_predicate> 中条件对 VT1 中的行进行筛选,让条件成立的行才会插入到 VT2 中。**此时数据还没有分组,所以不能在 WHERE 中出现对统计的过滤。


3. GROUP BY 阶段

GROUP 阶段按照指定的列名列表,将 VT2 中的行进行分组,生成 VT3。最后每个分组只有一行。在 GROUP BY 阶段,数据库认为两个 NULL 值是相等的,因此会将 NULL 值分到同一个分组中。


4. HAVING 阶段

该阶段根据 HAVING 子句中出现的谓词对 VT3 的分组进行筛选,并将符合条件的组插入到 VT4 中。COUNT(expr) 会返回 expr 不为 NULL 的行数,count(1)、count(*) 会返回包括 NULL 值在内的所有数量。


5. SELECT 阶段

这个阶段是投影的过程,处理 SELECT 子句提到的元素,产生 VT5。这个步骤一般按下列顺序进行:

  • 计算 SELECT 列表中的表达式,生成 VT5-1。

  • 若有 DISTINCT,则删除 VT5-1 中的重复行,生成 VT5-2。


6. ORDER BY 阶段

根据 ORDER BY 子句中指定的列明列表,对 VT5-2 中的行,进行排序,生成 VT6。如果不指定排序,数据并非总是按照主键顺序进行排序的。NULL 被视为最小值。


7. LIMIT 阶段

取出指定行的记录,产生虚拟表 VT7,并返回给查询用户。LIMIT n, m 的效率是十分低的,一般可以通过在 WHERE 条件中指定范围来优化 WHERE id > ? limit 10。

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

占星安啦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值