SQL 查询条件放在LEFT OUTER JOIN 的ON语句后与放在WHERE中的区别
这两种条件放置的位置不同很容易让人造成混淆,以致经常查询出莫名其妙的结果出来,特别是副本的条件与主表不匹配时,下面以A,B表为例简单说下我的理解。
首先要明白的是:
跟在ON 后面的条件是对参与左联接的数据进行筛选,即在左联接之前起作用。
跟在WHERE后的条件是对左联接得到的结果集进行筛选,即在左联接之后起作用。
我直接把我的结论发出来,建议朋友们自行测试一下,下面是结论:
1) 如果条件是由主表和副表之间的字段构成,那么放在ON后与放在WHERE子条件中所得到的结果是一样,即这种条件可以随便放,甚至在SQL中建视图时,会自动优化放到ON条件后。
如下:
select * from A LEFT OUTER JOIN B ON A.Id=B.UserId AND A.Name=B.UserName
select * from A LEFT OUTER JOIN B ON A.Id=B.UserId WHERE A.Name=B.UserName
上面两个语句的结果是一样的,如果用这条语句去建视图,SQL管理器会自动优化成第一句的写法,大家可以亲自试验下。
2)如果条件是由进行左联接的两个表中的一个表的字段构成,则结果会很不一样。
1:select * from A LEFT OUTER JOIN B ON A.Id=B.UserId AND B.IsDel=0 (IsDel意思为记录是否删除,0为否,1为是。)
2:select * from A LEFT OUTER JOIN B ON A.Id=B.UserId WHERE B.IsDel=0
以上两句语句使用时要非常注意,这两种写法得到的数据是不一样的。
第一句的意思是:在进行左联接前,先从表B中筛选出没有标记为删除的数据后得到的结果再与A表进行左联接。
而第二句的意思是:在A,B表进行左联接后的,再对得到的结果进行“B.IsDel=0”条件过滤。
如果A表中有2条数据,在B表中都能匹配上,那么得到的结果是一样的,但是,假设A中只有一条记录在B中能匹配上,那么两条语句得到的结果就不一样了。
因为两表左联接后得到的结果集中的对应B.IsDel的列(假设生命为B_IsDel)的值其实是NULL值,那么再进行“B_IsDel=0”,这条记录就会被过滤掉了,
即最终的结果是第一条语句有两条数据,第二条语句只有一条。
此外,还有下面这种更离奇的情况,假设我们的需求是对A,B两表进行左联接,同时希望过滤掉A表中已经被删除了的数据和B表中已经被删除了的数据。可能会有如下两种写法:
3:select * from A LEFT OUTER JOIN B ON A.Id=B.UserId AND A.IsDel=0 AND B.IsDel=0 (IsDel意思为记录是否删除,0为否,1为是。)
4:select * from A LEFT OUTER JOIN B ON A.Id=B.UserId WHERE A.IsDel=0 AND B.IsDel=0
语句4能得到想要的结果。
语句3,这种写法很少见,执行后,大家会发现语句3的结果中包含了A表中A.IsDel=1的记录,这是为什么呢?
原因很简单,因为它是左联接,下面解释一下:
我们知道左联接的逻辑是A表或者说主表中的数据都会出现在最终的结果集中,那么“A.IsDel=0”这个条件在语句3左联接的过程起到了什么作用呢?
其作用是系统在进行左联接时,先在A表中用"A.IsDel=0"条件过滤数据(假设过滤掉了R1这条数据),用过滤后的结果再与B表进行左联接,
但最后整个语句返回的结果集中极会包含R1这条数据,只不过这条记录对应的B表中的字段全部为NULL值。请大家自行测试理解。
此时,如果想要达到我们的目的,必需在WHERE子句中增加A.IsDel=0条件,即:
select * from A LEFT OUTER JOIN B ON A.Id=B.UserId AND A.IsDel=0 AND B.IsDel=0 WHERE A.IsDel=0
但上面这条语句比较逻辑,也完全没必要这么写,因此我的建议是:针对单表字段构成的筛选条件这种情况,最好的做法是直接将条件放到WHERE子句中。
SQL 查询条件放在LEFT OUTER JOIN 的ON语句后与放在WHERE中的区别的更多相关文章
- SQL查询条件生成小工具
最近运维数据,经常遇到需要在sql条件中个In('',''....)个字符串的情况,于是在网上找了个小工具改造一下,先用着: 效果如图: using System; using System.Coll ...
- 论Top与ROW_NUMBER读取第一页的效率问题及拼接sql查询条件
http://www.cnblogs.com/Leo_wl/p/4921799.html SELECT TOP * FROM users WHERE nID> And nID< ORDER ...
- sql查询条件为空的另类写法o( ̄▽ ̄)d
简单描述:今天看老大提交的代码,发现了一个有意思的事情,一条sql中判断条件是空,老大的写法,让我眼前一亮.直接上代码 代码: <select id="getxxxs" re ...
- sql查询条件参数为空
查询某些值为空的数据 select * from usertable where name is null or page is null
- sql 查询条件为拼接字符串 不能使用IN 使用patindex查询结果集
题目: 求组织机构ID在('5dc8de20-9f2f-465e-afcc-f69abecaee50','63549b63-1e0d-4269-98f4-013869d7f211','f7316bf3 ...
- sql查询当天,一周,一个月数据的语句
--查询当天: select * from info where DateDiff(dd,datetime,getdate())=0 --查询24小时内的: select * from info w ...
- LINQ to SQL系列四 使用inner join,outer join
先看一个最简单的inner join,在读取Student表时inner join Class表取的对应的Class信息: static void Main(string[] args) { usin ...
- 【转】SQL多条件模糊查询解决方案-存储过程
前言: 算法的基本特性在前几篇博客中已经做了详细的说明,经过不断的改进优化,到归仓的时候了,也就是说,该算法告一段落,不再更新. 作为最终的解决方案,简要的总结一下算法特性,以方便读者参阅. l ...
- MySQL从删库到跑路(五)——SQL查询
作者:天山老妖S 链接:http://blog.51cto.com/9291927 1.查询所有字段 在SELECT语句中使用星号“”通配符查询所有字段在SELECT语句中指定所有字段select f ...
随机推荐
- 网页icon和文本对齐神技 2016.03.23
一直以来icon和文本需要对齐都使用vertical-align: middle;的方法,但兼容性不理想.参考了鑫旭大大的博客,终于收获不用vertical-align可以对齐的神技,原博点这里. 代 ...
- 『重构--改善既有代码的设计』读书笔记----Replace Array with Object
如果你有一个数组,其中的元素各自代表不同东西,比如你有一个 QList<QString> strList; 其中strList[0]代表选手姓名,strList[1]代表选手家庭住址,很显 ...
- js获取天气
我们经常看到有的网站显示天气信息,它是怎么做出来的呢?今天就来分享一些关于js调用天气API的几种做法. 网上也能找到很多种方法,但是一般都是免费的不好用,好用的不免费. 以前用过新浪的天气api,查 ...
- Java实现http服务器(一)
基于Java实现Http服务器有多种多样的方法 一种轻量级的方式是使用JDK内置的com.sun.net.httpserver包下和sun.net.httpserver包下类提供的方法构建,该方法轻便 ...
- PC和单片机通过MODBUS RTU通信
最近研究了一下MODBUS通信,在STC12C5A60S2单片机上实现了MODBUS协议的部分功能,方便上位机从单片机系统上获取数据,比如由单片机获取的温度.湿度.或者控制信号的状态等.有了MODBU ...
- 一个C++程序员学习C#语言
感悟:C++是一门语法非常严谨的语言,只是指针就很难掌握,这其中肯定要经历很多折腾,特别是自学者. 折腾了一年半的C++,在即将毕业之际,对Unity3d游戏开发感兴趣,先是用cocos2dx开发了个 ...
- hadoop 2.x 安装包目录结构分析
bin:Hadoop最基本的管理脚本和使用脚本所在目录,这些脚本是sbin目录下管理脚本的基础实现,用户可以直接使用这些脚本管理和使用hadoop etc:Hadoop配置文件所在目录,包括core- ...
- 在debug模式下运行不报错,换到release模式下报找不到某某库或文件的错。。解决办法
我遇到的问题是:把edit secheme调到debug模式运行没有问题,然后调到release模式的时候报目录下没有libTuyoo.a 解决办法 把断开真机设备,用IOS device下relea ...
- python 大文件以行为单位读取方式比对
http://www.cnblogs.com/aicro/p/3371986.html 先前需要做一个使用python读取大文件(大于1G),并逐条存入内存进行处理的工作.做了很多的尝试,最终看到了如 ...
- Spring与Oauth2整合示例 spring-oauth-server
原文地址:http://www.oschina.net/p/spring-oauth-server?fromerr=vpTctDBF