SQL中过滤条件放在on和where中的区别

转自:https://blog.youkuaiyun.com/u013468917/article/details/61933994

join过程可以这样理解:首先两个表做一个笛卡尔积,on后面的条件是对这个笛卡尔积做一个过滤形成一张临时表,如果没有where就直接返回结果,如果有where就对上一步的临时表再进行过滤。下面看实验:

1.  先执行inner join:

select * from person p inner join account a on p.id=a.id and p.id!=4 and a.id!=4;

select * from person p inner join account a on p.id=a.id where p.id!=4 and a.id!=4;

结果没有区别,前者是先求笛卡尔积然后按照on后面的条件进行过滤,后者是先用on后面的条件过滤,再用where的条件过滤。

2. 再看看左连接left join

select * from person p left join account a on p.id=a.id and p.id!=4 and a.id!=4;

这下看出来不对了,id为4的记录还在,这是由left join的特性决定的,使用left join时on后面的条件只对右表有效(可以看到右表的id=4的记录没了

select * from person p left join account a on p.id=a.id where p.id!=4 and a.id!=4;

where的过滤作用就出来了。。。

结果的关键原因就是 left join,right join,full join 的特殊性。

不管 on 上的条件是否为真都会返回 left 或 right 表中的记录,full 则具有 left 和 right 的特性的并集。

而 inner jion 没这个特殊性,则条件放在 on 中和 where 中,返回的结果集是相同的。

 

<think>嗯,用户问的是Oracle SQLONWHERE过滤条件时的区别。首,我需要回忆一下ONWHERESQL查询中的作用。记得ON是用于连接表的条件,而WHERE是用于过滤结果集的。不过用户可能想知道更具体的区别,特别是在不同的连接类型下,比如内连接外连接。 根据引用[3]提到的,left join、right join、full join这些外连接的情况下,不管ON条件是否为真,都会返回左表或右表的所有记录。而inner join的话,ONWHERE的效果可能是一样的。不过这可能不完全准确,需要再仔细想想。 比如,当使用LEFT JOIN时,如果在ON里加条件,即使条件不满足,左表的记录还是会保留,而右表的部分会用NULL填充。但如果把同样的条件放在WHERE里,那么不满足条件的记录会被过滤掉,导致左表中不符合条件的记录也被排除,这样可能就不是LEFT JOIN的效果了。引用[2]也提到,外连接时,条件放在WHERE子句可能导致数据丢失,所以应该放在ON里。 那内连接的话,比如INNER JOIN,ONWHERE区别可能不大,因为内连接本身就会根据ON条件来匹配,但如果在ON里加额外的条件,可能影响连接的结果,而WHERE则是在连接后的结果上进行过滤。不过引用[3]说inner join情况下,ONWHERE的结果集是相同的,这可能是指当ON条件WHERE条件都是针对连接条件时,结果相同?还是说有其他情况? 比如,假设有一个INNER JOIN,ON条件是A.id = B.id AND B.some_col = 1,而另一个情况是INNER JOIN ON A.id = B.id,然后在WHERE里加上B.some_col = 1。这两种情况的结果是否相同?可能相同,因为内连接会根据ON条件匹配,然后WHERE过滤。但是如果ON中的条件影响了连接的行,而WHERE条件进一步过滤,这时候可能会有不同的结果吗? 不过根据引用[3],inner join时条件放在ONWHERE结果相同,可能是在某些情况下,比如当ON条件只是等值连接,而WHERE条件是额外的过滤。但如果是更复杂的条件,可能会有不同?需要具体例子来说明。 用户可能需要知道何时使用ON,何时使用WHERE,特别是在外连接的情况下。例如,当需要保留主表的所有记录时,即使从表不符合条件,应该把条件放在ON里,而不是WHERE里,否则会导致主表的记录被过滤掉。 另外,引用[1]中提到,编写查询时,有时候放在ONWHERE的结果看起来一样,但其实在特定情况下会有差异。所以需要明确两者的执行顺序适用范围。 总结一下,区别主要在于连接类型:外连接时,ON条件影响连接过程,保留主表数据;WHERE条件在连接后过滤,可能导致主表数据丢失。而内连接时,ONWHERE可能效果相同,因为内连接本身就会过滤不匹配的行。 还需要考虑性能方面,比如条件放在ON可能在连接过程中提前过滤,减少连接的数据量,而WHERE是在连接后过滤,可能效率稍低。不过这可能取决于优化器的处理方式。 最后,用户可能需要示例来理解不同情况下的结果差异,所以回答中应该包含具体的例子,比如LEFT JOIN时ONWHERE区别,以及INNER JOIN时的对比。</think>### Oracle SQLONWHERE过滤条件区别 在Oracle SQL中,`ON``WHERE`虽然都用于筛选数据,但**作用阶段适用场景不同**,尤其在多表连接时差异显著。 --- #### 1. **作用阶段的区别** - **`ON`子句**: 用于定义**表连接的条件**,属于连接操作的一部分。它在生成临时结果集时生效,直接影响哪些行会被连接。 - **外连接(LEFT/RIGHT/FULL JOIN)**:即使`ON`中的条件不满足,主表数据仍会被保留,从表字段以`NULL`填充[^3]。 - **内连接(INNER JOIN)**:`ON`条件仅筛选满足条件的行进行连接。 - **`WHERE`子句**: 在连接完成后对结果集进行**最终过滤**。它会剔除所有不满足条件的行,无论主表还是从表的数据[^2]。 --- #### 2. **外连接中的典型差异** **示例场景**: 表`employees`(员工表)`departments`(部门表),使用`LEFT JOIN`查询所有员工及其部门信息。 - **条件放在`ON`中**: ```sql SELECT e.name, d.department_name FROM employees e LEFT JOIN departments d ON e.department_id = d.department_id AND d.department_name = 'IT'; ``` **结果**:所有员工都会被列出,但仅`department_name='IT'`的部门信息显示,非IT部门的员工对应字段为`NULL`。 - **条件放在`WHERE`中**: ```sql SELECT e.name, d.department_name FROM employees e LEFT JOIN departments d ON e.department_id = d.department_id WHERE d.department_name = 'IT'; ``` **结果**:仅保留部门为`IT`的员工,其他员工因`WHERE`过滤而被剔除。 --- #### 3. **内连接中的等效性** 对于`INNER JOIN`,`ON``WHERE`的筛选效果通常一致: ```sql -- 方式1:条件ON中 SELECT * FROM tableA INNER JOIN tableB ON tableA.id = tableB.id AND tableB.status = 1; -- 方式2:条件WHERE中 SELECT * FROM tableA INNER JOIN tableB ON tableA.id = tableB.id WHERE tableB.status = 1; ``` **两者结果相同**,因为内连接会按`ON`条件匹配,再隐式应用`WHERE`过滤[^3]。 --- #### 4. **性能与最佳实践** - **外连接**:若需保留主表数据,将过滤条件放在`ON`中;若需过滤结果,使用`WHERE`。 - **动态条件**:复杂筛选可通过动态SQL拼接`WHERE`条件,但需注意临时表的使用(如引用[^4]提到的`EXECUTE IMMEDIATE`)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值