SQL中on和where的使用及其差异
在编写SQL脚本中,多表连接查询操作需要使用到on和where条件,但是经常会混淆两者的用法,从而造成取数错误。为此,使用测试数据进行总结如下:




SELECT A1.User_Id
,A1.Month_Id
,A1.Brand_Id
,A1.Rate
,A2.User_Id
,A2.Month_Id
,A2.Type_Id
FROM table_a A1
LEFT JOIN table_b A2
ON A1.User_Id=A2.User_Id
AND A1.Month_Id=A2.Month_Id
;
最终的记录数等于主表的记录数。

SELECT A1.User_Id
,A1.Month_Id
,A1.Brand_Id
,A1.Rate
,A2.User_Id
,A2.Month_Id
,A2.Type_Id
FROM table_a A1
LEFT JOIN table_b A2
ON A1.User_Id=A2.User_Id
AND A1.Month_Id=A2.Month_Id
WHERE A1.Brand_Id='501B03'
;


SELECT A1.User_Id
,A1.Month_Id
,A1.Brand_Id
,A1.Rate
,A2.User_Id
,A2.Month_Id
,A2.Type_Id
FROM table_a A1
LEFT JOIN table_b A2
ON A1.User_Id=A2.User_Id
AND A1.Month_Id=A2.Month_Id
WHERE A1.Brand_Id='501B03'
AND A2.Type_Id=10
;

进一步说明,where条件是对连接产生的查询结果集的二次筛选。
SELECT A1.User_Id
,A1.Month_Id
,A1.Brand_Id
,A1.Rate
,A2.User_Id
,A2.Month_Id
,A2.Type_Id
FROM table_a A1
LEFT JOIN table_b A2
ON A1.User_Id=A2.User_Id
AND A1.Month_Id=A2.Month_Id
AND A1.Brand_Id='501B03'
;


SELECT A1.User_Id
,A1.Month_Id
,A1.Brand_Id
,A1.Rate
,A2.User_Id
,A2.Month_Id
,A2.Type_Id
FROM table_a A1
LEFT JOIN table_b A2
ON A1.User_Id=A2.User_Id
AND A1.Month_Id=A2.Month_Id
AND A2.Type_Id=10
;


总结如下:这里添加了对被连接表的On条件,这个条件也不会影响主表在最后结果集中的记录,它的作用主要是对被连接表首先进行一次筛选,它会让符合这个条件的被连接表中的记录去参与与主表的连接操作,其他不符合on条件的记录根本就没有机会参与与主表的连接。
SELECT A1.User_Id
,A1.Month_Id
,A1.Brand_Id
,A1.Rate
,A2.User_Id
,A2.Month_Id
,A2.Type_Id
FROM table_a A1
LEFT JOIN table_b A2
ON A1.User_Id=A2.User_Id
AND A1.Month_Id=A2.Month_Id
AND A1.Brand_Id='501B03'
AND A2.Type_Id=10
;




SELECT A1.User_Id
,A1.Month_Id
,A1.Brand_Id
,A1.Rate
,A2.User_Id
,A2.Month_Id
,A2.Type_Id
FROM table_a A1
LEFT JOIN table_b A2
ON A1.User_Id=A2.User_Id
;

这样可以看到,最后查询结果集的记录数不再是14条记录,而是15条,这说明了一点,最后的结果集中的记录数并不是和主表中记录数一致的,而是由主表和被连接表根据连接条件共同确定的,还可以说明的一点是,不论on条件是什么样,多简单多复杂,只要没有where条件,最后的查询结果集中的记录数不会少于主表记录数。对于这个例子,主表中的14条记录都会进入结果表,由于主表中的连接条件只有User_Id相等,因此,对于A2表中的User_Id=989832由于存在两条记录,因此都会与A1表User_Id=989832的那一条记录相连,因此产生了两条连接结果记录,所以使得最后的结果集增至15条记录。
SELECT A1.User_Id
,A1.Month_Id
,A1.Brand_Id
,A1.Rate
,A2.User_Id
,A2.Month_Id
,A2.Type_Id
FROM table_a A1
LEFT JOIN table_b A2
ON A1.User_Id=A2.User_Id
AND A1.Month_Id=A2.Month_Id
;
上面给A1和A2表的连接条件增加了一个Month_Id相等的条件,这样只有满足这一条件的A2表记录才会参与连接,这样就对A2表中的User_Id=989832剔除了一条记录,所以最后连接只产生了14条记录。


SELECT a1.User_Id
,a1.User_Id
,a1.Brand_Id AS brand_rank1
,a2.Brand_Id AS brand_rank2
,a3.Brand_Id AS brand_rank3
FROM table_c AS a1
LEFT JOIN table_c AS a2
ON a1.Month_Id=a2.Month_Id
AND a1.User_Id=a2.User_Id
AND a2.Rank_Id=2
LEFT JOIN table_c AS a3
ON a1.Month_Id=a3.Month_Id
AND a1.User_Id=a3.User_Id
AND a3.Rank_Id=3
WHERE a1.Rank_Id=1
;

SELECT a1.User_Id
,a1.User_Id
,a1.Brand_Id AS brand_rank1
,a2.Brand_Id AS brand_rank2
,a3.Brand_Id AS brand_rank3
FROM table_c AS a1
LEFT JOIN table_c AS a2
ON a1.Month_Id=a2.Month_Id
AND a1.User_Id=a2.User_Id
LEFT JOIN table_c AS a3
ON a1.Month_Id=a3.Month_Id
AND a1.User_Id=a3.User_Id
WHERE a1.Rank_Id=1
AND a2.Rank_Id=2
AND a3.Rank_Id=3
;
查询结果:

SQL中on和where的使用及其差异的更多相关文章
- SQL中Round(),Floor(),Ceiling()函数的浅析
项目中的一个功能模块上用到了标量值函数,函数中又有ceiling()函数的用法,自己找了一些资料,对SQL中这几个函数做一个简单的记录,方便自己学习.有不足之处欢迎拍砖补充 1.round()函数遵循 ...
- 关于sql中in 和 exists 的效率问题,in真的效率低吗
原文: http://www.cnblogs.com/AdamLee/p/5054674.html 在网上看到很多关于sql中使用in效率低的问题,于是自己做了测试来验证是否是众人说的那样. 群众: ...
- 学习sql中的排列组合,在园子里搜着看于是。。。
学习sql中的排列组合,在园子里搜着看,看到篇文章,于是自己(新手)用了最最原始的sql去写出来: --需求----B, C, F, M and S住在一座房子的不同楼层.--B 不住顶层.C 不住底 ...
- SQL中distinct的用法
SQL中distinct的用法 1.作用于单列 2.作用于多列 3.COUNT统计 4.distinct必须放在开头 5.其他 在表中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出 ...
- hibernate中java类的成员变量类型如何映射到SQL中的数据类型变化
hibernate映射文件??.hbm.xml配置映射元素详解--Hibernate映射类型 在从Hibernate的java的成员类型映射到SQL中的数据类型,其内映射方式它满足,SQL可以自己调制 ...
- C#调用SQL中的存储过程中有output参数,存储过程执行过程中返回信息
C#调用SQL中的存储过程中有output参数,类型是字符型的时候一定要指定参数的长度.不然获取到的结果总是只有第一字符.本人就是由于这个原因,折腾了很久.在此记录一下,供大家以后参考! 例如: ...
- sql中case when语句的使用-来自网摘文章
Case具有两种格式.简单Case函数和Case搜索函数. --简单Case函数 CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '其他' END ...
- SQL中inner join、outer join和cross join的区别
对于SQL中inner join.outer join和cross join的区别简介:现有两张表,Table A 是左边的表.Table B 是右边的表.其各有四条记录,其中有两条记录name是相同 ...
- SQL中对于两个不同的表中的属性取差集except运算
SQL中对两个集合取差集运算,使用except关键字,语法格式如下: SELECT column_name(s) FROM table_name1 EXCEPT SELECT column_name( ...
随机推荐
- 教你 Shiro 整合 SpringBoot,避开各种坑(山东数漫江湖)
依赖包 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-sprin ...
- OpenCVSSDpython目标探测对象检测
1.请参考大牛博客链接 https://www.aiuai.cn/aifarm822.html
- ACC026简要题解
这场AGC是时间正好在NOI之前休养生息的日子里,果断选择了放弃(虽然也从没有用大号打过).在随便做完了前几题之后就踏上了去长沙的旅程.NOI系列比赛总是休闲无比,咕咕不断,竟然连开幕式都能咕,今天A ...
- 【EverydaySport】健身笔记——静态牵拉
静态牵拉一般在运动后进行,可以有效的提高肌肉的柔韧性和关节的灵活性,预防和缓解疼痛. 每个动作达到自己活动范围的最大,有牵拉感即说明有效,静态保持至少30秒,切勿震荡,进行2组. 1 大腿前群牵拉 2 ...
- jstorm系列-1:入门
一. Storm整体介绍 Storm 是一个类似Hadoop MapReduce的系统, 用户按照指定的接口实现一个任务,然后将这个任务递交给JStorm系统,Jstorm将这 ...
- tinyhttpd ------ C 语言实现最简单的 HTTP 服务器
工作流程: 1>服务器启动,在指定端口或随机选取端口绑定httpd服务. 2>收到一个http请求时(其实就是listen端口accept的时候),派生一个线程运行accept_reque ...
- Java Socket编程基础篇
原文地址:Java Socket编程----通信是这样炼成的 Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Sock ...
- mysql:视图、触发器、事务、存储、函数、流程控制
阅读目录 一 视图 二 触发器 三 事务 四 存储过程 五 函数 六 流程控制 回到顶部 一 视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只 ...
- linux下输入密码不回显
这几天在做一个登陆的程序,需要将输入的密码屏蔽掉,自己百度,找到了两种方法,先贴下第一种方法, #include<stdio.h> #include<unistd.h> int ...
- hdu5798
官方题解: 考虑去掉abs符号,发现只有相邻两个数的最高位被影响了才会影响abs的符号,所以可以按照最高位不一样的位置分类,之后考虑朴素枚举x从0到2^20,每次的复杂度是O(400),无法通过,考虑 ...