表连接on 和where的区别

本文深入探讨了SQL中不同连接类型(INNER JOIN, LEFT JOIN, RIGHT JOIN)的特点与区别,通过实例解析了ON与WHERE子句在数据筛选过程中的作用及效率差异。

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

最近项目中碰到一个有关多表链接on 和where条件下数据的变换问题。做个简单整理:
select count(*) from “SAPHANADB”.“CDHDR” SCR
inner JOIN “SAPHANADB”.“CDPOS” SCS ON SCR.MANDANT = SCS.MANDANT AND SCR.OBJECTCLAS = SCS.OBJECTCLAS
AND SCR.OBJECTID = SCS.OBJECTID
AND SCR.CHANGENR = SCS.CHANGENR and (SCS.tabname=‘MARC’ or SCS.tabname=‘MBEW’ )
where SCR.objectclas = ‘MATERIAL’
在这里插入图片描述
可以看到显示有16805条数据,将where改为and
在这里插入图片描述
发现数据量没有变化。然后我们将inner join改为left join 和right join 看看
left where left  andleft join

right and
right whererighr join

很明显,数据量会发生变化。这是因为
当使用 left join 时,无论on的条件是否满足,都会返回左表的所有记录,对于满足的条件的记录,两个表对应的记录会连接起来,对于不满足条件的记录,那右表字段全部是null
当使用 right join 时,on与where类似,只不过是全部返回右表的所有记录
当使用 inner join 时,on与where完全相同。
on是在生成中间的临时表时起作用的先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,在数据比较多的情况下效率上要比较好点,where是生成临时表之后对连接表再进行过滤。

<think>我们正在讨论多查询中ONWHERE区别及使用场景。根据提供的引用,特别是引用[1]引用[5]中的内容,可以总结如下:1.**ON子句**:-专门用于JOIN操作中,用于指定之间的连接条件。-作用:决定两个如何连接,即哪些行应该被匹配在一起。-应用场景:在连接时,基于某些列的值(如外键关系)匹配行。例如,连接订单客户,基于客户ID(`ONorders.customer_id=customers.customer_id`)。2.**WHERE子句**:-用于过滤结果集,可以在SELECT、UPDATE、DELETE语句中使用。-作用:对FROM子句返回的结果集(包括连接后的结果)进行过滤,只保留满足条件的行。-应用场景:在连接完成后,基于某些条件筛选行。例如,只查询订单金额大于100的订单(`WHEREorders.amount>100`)。**关键区别**:-**执行顺序**:在连接操作中,ON子句在连接过程中执行(决定如何连接),而WHERE子句在连接完成后执行(过滤结果)。-**影响范围**:ON子句影响连接本身(决定哪些行被包含在连接结果中),WHERE子句影响最终结果(决定连接结果中保留哪些行)。-**性能影响**:在连接条件上使用ON子句(而不是WHERE)可以让优化器更有效地使用索引,避免不必要的全扫描。**外连接的特殊情况(引用[2][4])**:-对于左外连接(LEFTJOIN):-ON子句用于指定连接条件,并决定右中哪些行与左匹配。-WHERE子句则用于过滤最终结果(包括左的列)。-如果对右的列在WHERE中加条件,会导致未匹配的行被过滤掉(因为右列值为NULL,不满足条件),从而退化为内连接的效果。-若要对右进行过滤而不影响左行数,应将这些条件放在ON子句中。###示例说明####场景1:内连接(INNERJOIN)```sqlSELECT*FROMordersoINNERJOINcustomerscONo.customer_id=c.customer_id--连接条件:只匹配有订单的客户WHEREo.amount>100;--连接后过滤:只显示金额>100的订单```####场景2:左外连接(LEFTJOIN)```sql--查询所有客户及其订单(即使没有订单)SELECT*FROMcustomerscLEFTJOINordersoONc.customer_id=o.customer_id--连接条件:匹配客户的订单WHEREo.order_date>='2024-01-01';--注意:这会过滤掉没有订单的客户(因为o.order_date为NULL)--正确保留所有客户的写法(将日期条件移至ON子句):SELECT*FROMcustomerscLEFTJOINordersoONc.customer_id=o.customer_idANDo.order_date>='2024-01-01';--在连接时过滤右```###核心原则1.**连接条件放ON子句**:关联时,匹配条件(如`table1.column=table2.column`)应放在ON子句中。2.**结果过滤放WHERE子句**:业务过滤条件(如日期范围、数值阈值)放在WHERE子句,除非需要保留主所有行(外连接时)。3.**外连接的过滤陷阱**:LEFTJOIN的右条件写在WHERE中会导致主数据丢失。---###相关问题1.如何避免左外连接WHERE条件导致的主数据丢失?2.多连接时,ON子句能否包含非等值条件(如范围、函数)?3.使用WHERE过滤连接条件(如`table1.id=table2.id`)会产生什么后果?4.如何用执行计划(EXPLAIN)分析ONWHERE的性能差异?</think> ### 📚 多查询中 `ON` `WHERE` 的区别及使用场景 基于引用内容的核心总结(引用[1][2][4][5]): #### 🔍 **本质区别** | **特性** | **`ON` 子句** | **`WHERE` 子句** | |----------------|--------------------------------------------------|---------------------------------------------------| | **作用阶段** | 连接过程中执行(连接时生效) | 连接完成后执行(结果集过滤) | | **核心用途** | 定义间的**连接匹配条件**(如外键关系) | 对最终结果集进行**数据过滤** | | **结果影响** | 决定哪些行被包含在连接结果中 | 决定连接结果中保留哪些行 | | **外连接现** | 右不满足条件时,左数据仍保留(补 `NULL`) | 直接过滤掉不满足条件的行(可能导致左数据丢失) | --- #### ⚙️ **使用场景对比** **示例结构**: - `orders`(订单):`order_id`, `customer_id`, `amount` - `customers`(客户):`customer_id`, `name` ##### 场景1:基础连接匹配(用 `ON`) ```sql -- 获取所有订单及对应客户名(包含无客户名的订单) SELECT o.order_id, c.name FROM orders o LEFT JOIN customers c ON o.customer_id = c.customer_id -- 连接条件在此定义 ``` ✅ **作用**: 连接时通过 `customer_id` 匹配,右无匹配时保留左数据(`name` 显示为 `NULL`)。 ##### 场景2:连接后过滤(用 `WHERE`) ```sql -- 仅显示订单金额>100的订单及客户名 SELECT o.order_id, c.name FROM orders o LEFT JOIN customers c ON o.customer_id = c.customer_id WHERE o.amount > 100 -- 结果集过滤在此定义 ``` ✅ **作用**: 先完成连接操作,再过滤掉 `amount <= 100` 的订单。 ##### ❗ 易错场景:外连接中混淆二者 ```sql -- ❌ 错误:意图保留所有订单,但实际丢失了部分左数据 SELECT o.order_id, c.name FROM orders o LEFT JOIN customers c ON o.customer_id = c.customer_id WHERE c.name IS NOT NULL -- WHERE过滤导致LEFT JOIN退化为INNER JOIN ``` ✅ **修正方案**(将过滤条件移到 `ON`): ```sql SELECT o.order_id, c.name FROM orders o LEFT JOIN customers c ON o.customer_id = c.customer_id AND c.name IS NOT NULL -- 连接时直接过滤右 ``` --- #### 💡 **关键结论**(引用[1][5]) 1. **连接必用 `ON`** 关联匹配条件(如 `a.id=b.id`)必须写在 `ON` 中,避免笛卡尔积或性能问题[^1]。 2. **过滤优选 `WHERE`** 业务筛选条件(如日期范围、数值阈值)推荐写在 `WHERE`。 3. **外连接慎用 `WHERE`** 左外连接需保留主数据时,右过滤条件应写在 `ON` 中,否则会丢失主数据(引用[2][4])。 4. **性能影响** `ON` 条件在连接时过滤可减少临时大小,比 `WHERE` 更高效(尤其关联字段有索引时)[^1][^5]。 --- ### 🔄 **示意图:执行流程差异** ```mermaid graph TD A[开始查询] --> B{JOIN操作} B --> C[用ON条件匹配数据] C --> D[生成连接结果集] D --> E{应用WHERE过滤} E --> F[返回最终结果] ``` --- ### 📌 相关问题 1. 如何避免左外连接中 `WHERE` 条件导致主数据丢失? 2. 多连接时,`ON` 子句能否包含非等值条件(如 `ON a.date > b.date`)? 3. 如何用执行计划(`EXPLAIN`)验证 `ON` `WHERE` 的性能差异? 4. 为什么说 `LEFT JOIN` 的 `WHERE` 条件错误使用会退化为内连接
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值