You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL含UNION ALL的SELECT查询执行顺序解析咨询

MySQL中该SELECT查询的完整执行流程解析

测试用SQL代码

create table student
(
ROLL_NO int,
NAME varchar(20),
ADDRESS varchar(20),
PHONE varchar(20),
Age int);

insert into student
values(1,'HARSH','DELHI','9036478414',18),(2,'PRATIK','BIHAR','9945127136',19),
      (3,'RIYANKA','SILIGURI','8618572816',20),(4,'DEEP','RAMNAGAR','8088648668',18),
      (5,'SAPTARHI','KOLKATA','8147513582',19),(6,'DHANRAJ','BARABAJAR','8123186181',20),
      (7,'ROHIT','BALURGHAT','9742111333',18),(8,'NIRAJ','ALIPUR','7851336571',19);

create table studentcourse
(
COURSE_ID int,
ROLL_NO int);

insert into studentcourse
values(1,1),(2,2),(2,3),(3,4),(1,5),(4,9),(5,10),(4,11);


select student.name,studentcourse.COURSE_ID
from student right join studentcourse
on studentcourse.ROLL_NO=student.ROLL_NO
union all
select student.NAME,studentcourse.COURSE_ID
from student left join studentcourse
on studentcourse.ROLL_NO=student.ROLL_NO
where student.ROLL_NO is null or studentcourse.COURSE_ID is null;

问题背景

我尝试通过该查询在全连接场景下获取重复NULL值,此前认为WHERE子句在FROM与JOIN子句之后执行,但实际似乎UNION ALL先于WHERE子句执行,恳请解析该SELECT查询在MySQL中的完整执行流程。

执行流程拆解

MySQL没有原生的FULL JOIN,你这里用RIGHT JOIN + LEFT JOIN + UNION ALL模拟全连接效果,但整个查询的执行逻辑是先分别执行两个子SELECT语句,再用UNION ALL合并结果,并非你误以为的UNION ALL先于WHERE执行。具体步骤如下:

1. 执行第一个子SELECT语句

select student.name,studentcourse.COURSE_ID
from student right join studentcourse
on studentcourse.ROLL_NO=student.ROLL_NO
  • 第一步:处理RIGHT JOIN关联逻辑
    RIGHT JOIN会保留右表(studentcourse)的所有行,当左表(student)中无匹配ROLL_NO的行时,左表字段填充为NULL。
    studentcourse共8行:
    • ROLL_NO为1-5的行能匹配student表数据,对应name为HARSH、PRATIK、RIYANKA、DEEP、SAPTARHI,COURSE_ID为对应值;
    • ROLL_NO为9、10、11的行在student表中无匹配,所以name为NULL,COURSE_ID分别为4、5、4。
  • 第二步:执行SELECT投影,得到8行结果集。

2. 执行第二个子SELECT语句

select student.NAME,studentcourse.COURSE_ID
from student left join studentcourse
on studentcourse.ROLL_NO=student.ROLL_NO
where student.ROLL_NO is null or studentcourse.COURSE_ID is null;

这个子查询内部严格遵循FROM/JOIN → WHERE → SELECT的执行顺序:

  • 第一步:处理LEFT JOIN关联逻辑
    LEFT JOIN会保留左表(student)的所有行,当右表(studentcourse)中无匹配ROLL_NO的行时,右表字段填充为NULL。
    student表共8行:
    • ROLL_NO为1-5的行能匹配studentcourse数据,COURSE_ID有对应值;
    • ROLL_NO为6、7、8的行在studentcourse表中无匹配,所以COURSE_ID为NULL。
  • 第二步:执行WHERE筛选
    筛选条件student.ROLL_NO is null or studentcourse.COURSE_ID is null中,student.ROLL_NO is null永远不会命中(LEFT JOIN保留了student的所有行,ROLL_NO均有值),最终只筛选出studentcourse.COURSE_ID is null的行——即ROLL_NO为6、7、8的3行,对应name为DHANRAJ、ROHIT、NIRAJ,COURSE_ID为NULL。
  • 第三步:执行SELECT投影,得到3行结果集。

3. 执行UNION ALL合并结果

将第一个子查询的8行结果和第二个子查询的3行结果直接合并(UNION ALL不会去重),最终得到11行结果,包含两类NULL场景:

  • name为NULL的行(来自studentcourse中无匹配的学生);
  • COURSE_ID为NULL的行(来自student中无选课记录的学生)。

内容的提问来源于stack exchange,提问作者Vighnesh Bhat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 06:45:09