SQL执行顺序join在where前面

博客讲述了在执行SQL查询时遇到的问题,即在LEFT JOIN后添加特定日期过滤条件导致无法获取A表中部分数据。通过使用CTE(Common Table Expression)作为子查询,先筛选B表的昨日数据,然后再与A表JOIN,成功解决了这个问题,确保了A表数据的完整显示。

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

  • 取a表和b表join的数据sql

原本意图是取a表的昨日分区数据和b表的昨日分区数据进行join,但是发现加上and b.dt = '${daily}'的条件后就取不到在a表中存在的数据了

select substr(a.create_time,1,7) create_month,a.service_id,a.unit_number,a.company_name,coalesce(b.unified_social_credit_code,'unknown') unified_social_credit_code
,a.company_id,b.company_id as company_id_b,a.dt,b.dt
from clouduser.dz_company a 
left join clouduser.dz_company_detail b on a.company_id = b.company_id
where a.dt = '${daily}' 
--and b.dt = '${daily}'
and substr(a.create_time,1,7) = '2022-09'
and a.company_name = '浙江港都电子有限公司';
  • 运行结果
    在这里插入图片描述
  • 原因是where执行是在join之后,join出来的临时表中,由于在b表中没有匹配到数据,所以b.dt为null,这时候执行where b.dt = '${daily}'的条件筛选不到这条数据。
  • 优化方法

现在子查询中将b表的昨日分区查询出来,再和a表join

with
r1 as (select * from clouduser.dz_company_detail where dt = '2022-10-17'),
r2 as (
select substr(a.create_time,1,7) create_month,a.service_id,a.unit_number,a.company_name,coalesce(b.unified_social_credit_code,'unknown') unified_social_credit_code
,a.company_id,b.company_id as company_id_b
from clouduser.dz_company a 
left join r1 b on a.company_id = b.company_id
where a.dt = '${daily}' 
--and b.dt = '${daily}'
and substr(a.create_time,1,7) = '2022-09'
and a.company_name = '浙江港都电子有限公司'
)
select * from r2;
  • 执行结果
    在这里插入图片描述

可以看到正常查询出a表中的数据了

### SQL 查询执行顺序解析 在SQL查询中,`SELECT`、`FROM` 和 `LEFT JOIN` 的逻辑处理顺序并不是按照它们在语句中的书写顺序执行的。实际上,数据库引擎内部遵循特定的执行流程。 #### 1. FROM 子句 这是整个查询的第一步,在此阶段,所有的表都会被读取并准备用于后续操作。对于涉及多个表的情况,如使用 `JOIN` 操作符时,也会在此步骤完成联接工作。当涉及到左连接 (`LEFT JOIN`) 时,即使右侧表没有匹配记录,左侧表的所有行仍然会被保留下来,并且右侧表对应的列将填充为 NULL 值[^1]。 ```sql FROM departments d LEFT JOIN employees e ON d.department_id = e.department_id ``` 这段代码表示从 `departments` 表开始,尝试与 `employees` 表基于部门ID进行关联;如果有不匹配的部分,则只显示来自 `departments` 表的数据,而缺失部分则用NULL代替。 #### 2. WHERE 条件过滤 一旦完成了数据源的选择和初步组合之后,就会应用任何指定于 `WHERE` 子句内的筛选条件。需要注意的是,虽然在这个例子中有 `WHERE` 关键字出现在最后面的位置上,但在实际运行过程中它是在 `JOIN` 完成后再做进一步限定作用的对象集合上的过滤[^4]。 ```sql WHERE d.department_name IN ('IT', 'Sales', 'Retail Sales') ``` 这里是对已经通过 `LEFT JOIN` 连接起来的结果集施加额外约束——仅限于某些特定名称下的部门条目参与最终计算。 #### 3. GROUP BY 分组聚合 接着会对满足上述两个阶段产生的中间结果实施分组汇总运算。这一步骤通常伴随着聚集函数的应用,比如求平均数(`AVG()`)等统计指标。 ```sql GROUP BY department_name, e.job_id ``` 该命令指示系统按部门名以及职位编号这两项属性来进行分类整理,并据此得出每一群体各自的薪资均值。 #### 4. SELECT 投影字段选取 到了这个环节才真正决定了返回给用户的列有哪些具体内容。此时可以自由挑选所需展示的信息项目,并允许对其进行重命名或其他形式变换。 ```sql SELECT d.department_name, e.job_id, AVG(e.salary) AS average_salary ``` 这条指令明确了要提取哪些信息作为输出的一部分,同时还定义了一个新的别名为 "average_salary" 的表达式代表员工工资平均水平。 #### 5. ORDER BY 排序安排 最后一环则是依据设定好的标准对所得列表重新排列次序以便更直观地呈现出来。 ```sql ORDER BY d.department_name, e.job_id; ``` 综上所述,尽管表面上看起来像是先选择了什么再去找哪里的数据,但实际上真正的执行路径是从底层向上逐步构建直至形成完整的答案视图[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值