SQL 中不同类型的表连接
http://www.linuxidc.com/Linux/2012-08/68035.htm
1、简介
在关系型数据库中,join操作是将不同的表中的数据联合在一起时非常通用的一种做法。首先让我们看看join是如何操作的,然后我们探索一下当join和where语句同时存在的时候的执行顺序问题,最后来谈一谈不同类型的join的顺序问题。
2、建立初始的测试表结构(建表语句到这里下载)
表建立完之后,将会看到如下三个表。
我们将通过以上三个表来演示join操作。这三个表都是用来做演示的,所以我并没有使用主键和外键。
3、表的笛卡尔乘积
一般情况下,我们使用两个表中的相关字段进行join操作,例如,employee表中的DeptId字段对应于Department表中的DepId字段,通过这种方式进行join。
下面的一个例子是不使用关联字段来做表的连接。这里TableA和TableB以笛卡尔乘积的方式连在了一起。笛卡尔乘积就是先从第一个表中取出一条记录,和第二章表中的每一条记录配合,然后再取出第二条记录,同样和第二张表的所有记录配合,直至第一张表中的所有记录都取完。所以最终的结果数量将是两张表的乘积。
4、join两张表
当我们想做两个表的连接,而不是像上面的例子一样得到大量的无用的结果的时候,我们就得从两张表中选取一个join列。我下面给出的例子是使用id作为join列的。我们可以通过这种方式使得结果只映射我们需要的那一部分,从而过滤掉了无用数据。
注意:在笛卡尔乘积表中的第一行和第五行满足了join的映射关系,从而被作为结果,其他的都被过滤掉了。
5、join多张表
上面的例子是join两张表,如果想join多张表,我们需要在上面的结果中选择一列,然后再在新表中选择一列,将这两者作为join字段,然后指定join的规则,这样我们理论上可以join任意多张表。
首先,Table_A和Table_B做了连接,就上上面的join两张表的例子,然后将join的结果作为一张表AB。再将AB与Table_C连接。
6、join类型
在两张不同的表做连接有3中join类型。
1、full join
2、inner join
3、outer join(left outer join、right outer join)
在上面两个例子中我们看到的是inner join。如果我们连接表自身就叫做self join。这个特殊类型不会混淆连接类型。
7、full join
full join和笛卡尔有些不同,笛卡尔积会获取所有可能的结果。而full join将匹配的结果与所有左边的表中不匹配右边的行和右边的表中所有不匹配左边的行加在一起,在不匹配的地方使用NULL代替。结果行数=匹配行数+左表剩余行数+右表剩余行数。
在上面的图片中,蓝色的行是两个表匹配的行。
第二行,左边绿色,右边红色的是不匹配的,左表中的行是存在的,而右表中的字段则被null填充。
第三行,左边红色,右边绿色的同样是不匹配的,右表中的行是存在的,而左表中的字段则被null填充。
8、left join
左连接(left join)保证左表中的所有行都有,而当不匹配的时候以NULL填充右表字段。
蓝色匹配,红色和绿色不匹配
9、right join
反过来,右连接(right join)保证右表中所有的行都有,而当不匹配的时候以NULL填充左表字段。
蓝色匹配,红色和绿色不匹配
10、inner join
inner join就是只列出匹配的行。
11、self join
表连接自身叫做self join。为了解释一下这个让我们看如下图中的employee表。EmployeeID是此表的主键,ReportsTo引用了此表的主键。我们可以想象成这样,ReportTo字段引用代表该雇员的上司,其上司同样也是雇员。
看如下例子
这里,有ReportTo指向的行是Manager,所以employee是左表,Manager是右表。
12、执行顺序
当连接中有where语句的时候我们需要注意连接和where的执行顺序问题。
1、将where语句先于join执行,因为执行完where查询的结果将会比较少,从而join操作性能会提升。
2、将where语句后与join执行。
以上两者将在inner join的时候返回同样的结果,但是当使用outer join的时候至少有一种连接操作的返回结果不同。看下面例子。
所以记住当外连接的时候尽量先执行join操作然后执行where语句。
13、连接的顺序
当你想将inner join和outer join同时使用的时候join的顺序也是非常重要的。
什么是连接的顺序?如果我像这样连接三张表【X inner Y】left Z,顺序就是先inner join再left join。
让我们回到上面的例子中,你想得到的结果是获取所有客户的名字,不管他们是否有订单。如果他们确实有一些订单,还要列出了客户订购的数量。
看如下的查询【先outer join再inner join】
1、在Orders和Customers中进行了right join。右连接能保证你获取所有Customer的信息,不管他是否有order。
2、现在上面的结果将和Order Details连接。但是我们需要注意的是,在右连接的结果中有两行roderid为null的,因为这两个customer并没有任何order,而在后面做inner join的时候,由于orderid为null,inner join将跳过这两行,从而导致这两个customer的信息被过滤掉了。
再让我们看看下面的这个查询【先inner join再outer join】
让我们分析一下为什么这才是我们想要的结果。
首先Order和Order Details表做inner join,所有匹配的结果都将被列出来,然后将此结果作为左表,Customer表作为右表,右表的所有行都将被列出来,不管其匹配与否(言外之意,那两个没有order的customer也将被列出来)。
所以,在我们同时使用inner join和outer join的时候一定要对连接的顺序做慎重考虑。
14、获取同样数据的其他办法
看如下查询
1、首先查询出Customers将其作为左表
2、然后将Orders表查询出来,仍然作为左表
3、然后查询出Order Details表将其作为右表与Orders表进行inner join。
4、最后Customers表将于第三步查询出的结果进行左连接。别忘了左连接将保证Customers表不丢失任何记录。
SQL 中不同类型的表连接的更多相关文章
- SQL中查看数据库各表的大小
SQL中查看数据库各表的大小 编写人:CC阿爸 2014-6-17 在日常SQL数据库的操作中,如何快速的查询数据库中各表中数据的大小. 以下有两种方法供参考: 第一种: create table # ...
- MySQL中基本的多表连接查询教程
一.多表连接类型1. 笛卡尔积(交叉连接) 在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者使用',' 如: SELECT * FROM table1 CROSS JOIN ...
- SQL 经典回顾:JOIN 表连接操作不完全指南
2017-02-23 小峰 ITPUB 点击上方“蓝字”可以关注我们哦  |转载自:码农网 |原文链接:www.codeceo.com/article/sql-join-guide.html ...
- Sql Server系列:多表连接查询
连接查询是关系数据中最主要的查询,包括内连接.外连接等.通过连接运算符可以实现多个表查询.内连接查询操作列出与连接条件匹配的数据行,它使用比较运算符比较被连接列的列值.SQL Server中的内连接有 ...
- 帆软SQL报异常:多表连接的时候出现错误:未明确定义列
我刚开始的代码: select dm_veh_jdcgz_mx.DAY_ID ,--日期 dm_veh_jdcgz_mx.GLBM ,--管理部门ID dm_veh_jdcgz_mx.SFZMHM , ...
- SQL中使用关键词创建表或字段
有时候我们给表或者字段命名时,会无意中选择了一个SQL中的关键字进行命名,然后就报错了: ERROR: syntax error at or near "limit" MySQL ...
- Sql 中text类型字段判断是否为空
用 len关键字,字段=''会报错:数据类型 text 和 varchar 在 equal to 运算符中不兼容. 正确方法: 1. 字段 is null 2. datalength(字段)=0 注: ...
- MS SQL 中判断 数据库, 存储过程,表,临时表,视图,函数,用户,用户创建对象 等是否存在 SQL脚本
摘自: http://www.111cn.net/database/mssqlserver/39107.htm sql判断存储过程是否存在 判断数据库教程是否存在 Sql代码 if exists (s ...
- Sql中如何将数据表的两个字段的值如何互换?
今天遇到一个数据表的两个列数据要互换,在网上找到并记录下. 直接用Sql就可以搞定,语法如下 --将数据表中两个列数据互换的语法-- update tabName set field1=field2, ...
随机推荐
- 你一无所知的CSS
也许标题有点夸大了.虽然不能完全保证大家都不知道这些,但是这也算是一个好机会检测下你是否知道或使用过下面的内容. Selectors Root :root { } 使用root可以让你在DOM中选择 ...
- linux下,Python 多版本共存,及Pip,Easy_install 安装扩展包
Python2与Python3共存 安装Python3后,建立ln,使用Python(Python2),Python3 来区分两个版本 使用sudo apt-get install python3-s ...
- 五种开源协议(GPL,LGPL,BSD,MIT,Apache)
什么是许可协议? 什么是许可,当你为你的产品签发许可,你是在出让自己的权利,不过,你仍然拥有版权和专利(如果申请了的话),许可的目的是,向使用你产品的人提供 一定的权限. 不管产品是免费向公众分发,还 ...
- js判断浏览器类型以及浏览器版本
判断浏览器类型: if navigator.userAgent.indexOf(”MSIE”)>0) {} //判断是否IE浏览器 if(isFirefox=navigator.userAg ...
- [uva11722&&cogs1488]和朋友会面Joining with Friend
几何概型,<训练指南>的题.分类讨论太神啦我不会,我只会萌萌哒的simpson强上~这里用正方形在y=x-w的左上方的面积减去在y=x+w左上方的面积就是两条直线之间的面积,然后切出来的每 ...
- Linux下C高手成长过程
建议学习路径: 首先先学学编辑器,vim, emacs什么的都行. 然后学make file文件,只要知道一点就行,这样就可以准备编程序了. 然后看看<C程序设计语言>K&R, ...
- [创业中, 寻求合作] 业务方向:车联网智能终端;APP蓝牙控制汽车;APP网络远程控制汽车 (联系电话:18503086002)
擅长领域 手机APP蓝牙控制汽车方案 手机APP网络远程控制汽车方案 手机APP与汽车车机的文件极速传输技术 车载OBD终端 (后装) 智能TBOX终端,Base on Linux,使用车规级硬件加密 ...
- 树莓派2安装使用小米WIfi(360 小度 腾讯wifi)
更新2015年11月16日,jessie内核版本号4.1.13(uname -a 可以查看)直接可以驱动MT7601U,无需手动编译. 截止2015-4-6,本文基于树莓派2,raspbian,内核版 ...
- bootstrap 水平表单
<form class="form-horizontal" role="form"> <div class="form-group& ...
- Node.js入门笔记(6):web开发方法
使用node进行web开发 用户上网流程: 表面上看:打开浏览器--输入网址--跳转--上网. 背后的过程是什么呢? http请求网址到指定的主机--服务器接收请求--服务器响应内容到用户浏览器--浏 ...