SQL内连接与外连接.docx
《SQL内连接与外连接.docx》由会员分享,可在线阅读,更多相关《SQL内连接与外连接.docx(16页珍藏版)》请在冰豆网上搜索。
![SQL内连接与外连接.docx](https://file1.bdocx.com/fileroot1/2023-5/31/ee535c75-98a5-45d8-9eca-7ae4fae17e42/ee535c75-98a5-45d8-9eca-7ae4fae17e421.gif)
SQL内连接与外连接
1.概述
1、联接(典型的联接运算,使用像=或<>之类的比较运算符)。
包括相等联接和自然联接。
联接使用比较运算符根据每个表共有的列的值匹配两个表中的行。
例如,检索students和courses表中学生标识号相同的所有行。
2、外联接。
外联接可以是左向外联接、右向外联接或完整外部联接。
在FROM子句中指定外联接时,可以由下列几组关键字中的一组指定:
1)LEFTJOIN或LEFTOUTERJOIN
左向外联接的结果集包括LEFTOUTER子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。
如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。
2)RIGHTJOIN或RIGHTOUTERJOIN
右向外联接是左向外联接的反向联接。
将返回右表的所有行。
如果右表的某行在左表中没有匹配行,则将为左表返回空值。
3)FULLJOIN或FULLOUTERJOIN
完整外部联接返回左表和右表中的所有行。
当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。
如果表之间有匹配行,则整个结果集行包含基表的数据值。
例子:
-------------------------------------------------
a表idnameb表idjobparent_id
131231
2四2342
3王武3344
a.id同parent_id存在关系
--------------------------------------------------
1)连接
selecta.*,b.*fromainnerjoinbona.id=b.parent_id
结果是
131231
2四2342
2)左连接
selecta.*,b.*fromaleftjoinbona.id=b.parent_id
结果是
131231
2四2342
3王武null
3)右连接
selecta.*,b.*fromarightjoinbona.id=b.parent_id
结果是
131231
2四2342
null3344
4)完全连接(不做过多概述)
selecta.*,b.*fromafulljoinbona.id=b.parent_id
结果是
131231
2四2342
null 3344
3王武null
2.连接(INNERJOIN)
连接(INNERJOIN):
有两种,显式的和隐式的,返回连接表中符合连接条件和查询条件的数据行。
(所谓的表就是数据库在做查询形成的中间表)。
例如:
下面的语句3和语句4的结果是相同的。
语句1:
隐式的连接,没有INNERJOIN,形成的中间表为两个表的笛卡尔积。
SELECTO.ID,O.ORDER_NUMBER,C.ID,C.NAME
FROMCUSTOMERSC,ORDERSO
WHEREC.ID=O.CUSTOMER_ID;
语句2:
显示的连接,一般称为连接,有INNERJOIN,形成的中间表为两个表经过ON条件过滤后的笛卡尔积。
SELECTO.ID,O.ORDER_NUMBER,C.ID,C.NAME
FROMCUSTOMERSCINNERJOINORDERSOONC.ID=O.CUSTOMER_ID;
3.外连接(OUTERJOIN):
外连不但返回符合连接和查询条件的数据行,还返回不符合条件的一些行。
外连接分三类:
左外连接(LEFTOUTERJOIN)、右外连接(RIGHTOUTERJOIN)和全外连接(FULLOUTERJOIN)。
三者的共同点是都返回符合连接条件和查询条件(即:
连接)的数据行。
不同点如下:
左外连接还返回左表中不符合连接条件单符合查询条件的数据行。
右外连接还返回右表中不符合连接条件单符合查询条件的数据行。
全外连接还返回左表中不符合连接条件单符合查询条件的数据行,并且还返回右表中不符合连接条件单符合查询条件的数据行。
全外连接实际是上左外连接和右外连接的数学合集(去掉重复),即“全外=左外UNION右外”。
说明:
左表就是在“(LEFTOUTERJOIN)”关键字左边的表。
右表当然就是右边的了。
在三种类型的外连接中,OUTER关键字是可省略的。
下面举例说明:
语句3:
左外连接(LEFTOUTERJOIN)
SELECTO.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROMORDERSOLEFTOUTERJOINCUSTOMERSCONC.ID=O.CUSTOMER_ID;
语句4:
右外连接(RIGHTOUTERJOIN)
SELECTO.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROMORDERSORIGHTOUTERJOINCUSTOMERSCONC.ID=O.CUSTOMER_ID;
注意:
WHERE条件放在ON后面查询的结果是不一样的。
例如:
语句5:
WHERE条件独立。
SELECTO.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROMORDERSOLEFTOUTERJOINCUSTOMERSCONC.ID=O.CUSTOMER_ID
WHEREO.ORDER_NUMBER<>'MIKE_ORDER001';
语句6:
将语句5中的WHERE条件放到ON后面。
SELECTO.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROMORDERSOLEFTOUTERJOINCUSTOMERSCONC.ID=O.CUSTOMER_IDANDO.ORDER_NUMBER<>'MIKE_ORDER001';
从语句5和语句6查询的结果来看,显然是不相同的,语句6显示的结果是难以理解的。
因此,推荐在写连接查询的时候,ON后面只跟连接条件,而对中间表限制的条件都写到WHERE子句中。
语句7:
全外连接(FULLOUTERJOIN)。
SELECTO.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROMORDERSOFULLOUTERJOINCUSTOMERSCONC.ID=O.CUSTOMER_ID;
注意:
MySQL是不支持全外的连接的,这里给出的写法适合Oracle和DB2。
但是可以通过左外和右外求合集来获取全外连接的查询结果。
语句8:
左外和右外的合集,实际上查询结果和语句7是相同的。
SELECTO.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROMORDERSOLEFTOUTERJOINCUSTOMERSCONC.ID=O.CUSTOMER_ID
UNION
SELECTO.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROMORDERSORIGHTOUTERJOINCUSTOMERSCONC.ID=O.CUSTOMER_ID;
4.SQL查询的基本原理:
两种情况介绍。
第一、单表查询:
根据WHERE条件过滤表中的记录,形成中间表(这个中间表对用户是不可见的);然后根据SELECT的选择列选择相应的列进行返回最终结果。
第二、两表连接查询:
对两表求积(笛卡尔积)并用ON条件和连接连接类型进行过滤形成中间表;然后根据WHERE条件过滤中间表的记录,并根据SELECT指定的列返回查询结果。
第三、多表连接查询:
先对第一个和第二个表按照两表连接做查询,然后用查询结果和第三个表做连接查询,以此类推,直到所有的表都连接上为止,最终形成一个中间的结果表,然后根据WHERE条件过滤中间表的记录,并根据SELECT指定的列返回查询结果。
理解SQL查询的过程是进行SQL优化的理论依据。
ON后面的条件(ON条件)和WHERE条件的区别:
ON条件:
是过滤两个表笛卡尔积形成中间表的约束条件。
WHERE条件:
在有ON条件的SELECT语句中是过滤中间表的约束条件。
在没有ON的单表查询中,是限制物理表或者中间查询结果返回记录的约束。
在两表或多表连接中是限制连接形成最终中间表的返回结果的约束。
从这里可以看出,将WHERE条件移入ON后面是不恰当的。
推荐的做法是:
ON只进行连接操作,WHERE只过滤中间表的记录。
总结
连接查询是SQL查询的核心,连接查询的连接类型选择依据实际需求。
如果选择不当,非但不能提高查询效率,反而会带来一些逻辑错误或者性能低下。
下面总结一下两表连接查询选择方式的依据:
1、查两表关联列相等的数据用连接。
2、Col_L是Col_R的子集时用右外连接。
3、Col_R是Col_L的子集时用左外连接。
4、Col_R和Col_L彼此有交集但彼此互不为子集时候用全外。
多个表查询的时候,这些不同的连接类型可以写到一块。
例如:
SELECTT1.C1,T2.CX,T3.CY
FROMTAB1T1
INNERJOINTAB2T2ON(T1.C1=T2.C2)
INNERJOINTAB3T3ON(T1.C1=T2.C3)
LEFTOUTERJOINTAB4ON(T2.C2=T3.C3);
WHERET1.X>T3.Y;
上面这个SQL查询是多表连接的一个示。
5.操作符下的左右连接
对于外连接,也可以使用“(+)”来表示。
关于使用(+)的一些注意事项:
1.(+)操作符只能出现在where子句中,并且不能与outerjoin语法同时使用。
2.当使用(+)操作符执行外连接时,如果在where子句中包含有多个条件,则必须在所有条件中都包含(+)操作符
3.(+)操作符只适用于列,而不能用在表达式上。
4.(+)操作符不能与or和in操作符一起使用。
5.(+)操作符只能用于实现左外连接和右外连接
左连接
用(+)来实现,这个+号可以这样来理解:
+表示补充,即哪个表有加号,这个表就是匹配表。
所以加号写在右表,左表就是全部显示,故是左连接。
SQL>Select*fromdavea,blbwherea.id=b.id(+); --注意:
用(+)就要用关键字where
右连接
用(+)来实现,这个+号可以这样来理解:
+表示补充,即哪个表有加号,这个表就是匹配表。
所以加号写在左表,右表就是全部显示,故是右连接。
SQL>Select*fromdavea,blbwherea.id(+)=b.id;
6.On与where的区别
数据库在通过连接两或多表来返回记录时,都会生成一中间的临时表,然后再将这临时表返回给用户。
在使用leftjion时,on和where条件的区别如下:
1、on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。
2、where条件是在临时表生成好后,再对临时表进行过滤的条件。
这时已经没有leftjoin的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。
假设有两表:
表1:
tab2idsize
110
220
330
表2:
tab2sizename
10AAA
20BBB
20CCC
两条SQL:
1、select*formtab1leftjointab2on(tab1.size=tab2.size)wheretab2.name=’AAA’
2、select*formtab1leftjointab2on(tab1.size=tab2.sizeandtab2.name=’AAA’)
第一条SQL的过程:
1、中间表
on条件:
tab1.size=tab2.size tab1.idtab1.sizetab2.sizetab2.name
11010AAA
22020BBB
22020CCC
330(null)(null)
||
2、再对中间表过滤
where条件:
tab2.name=’AAA’
tab1.idtab1.sizetab2.sizetab2.name
11010AAA
第二条SQL的过程:
1、中间表
on条件:
tab1.size=tab2.sizeandtab2.name=’AAA’
(条件不为真也会返回左表中的记录)tab1.idtab1.sizetab2.sizetab2.name
11010AAA
220(null)(null)
330(null)(null)
其实以上结果的关键原因就是leftjoin,rightjoin,fulljoin的特殊性,不管on上的条件是否为真都会返回left或right表中的记录,full则具有left和right的特性的并集。
而innerjion没这个特殊性,则条件放在on中和where中,返回的结果集是相同的。
心得:
外匹配,连接过滤,外即匹配又过滤用on和where搭配
7.图解SQL的连接与外连接
外连接就相当于多个业务表的一次合体,连接的条件必须是关键性的!
连接成功就可看成一表!
在oracle的SQL语句常用的连接有连接(innerjoin),外连接(outerjoin)等,连接又包括等值连接,非等值连接,自连接;而外连接又分为左连接和右连接。
其中默认的是连接的等值连接。
为了方便我们创建两最简易的表A、B,具体的表结构参看下面,来分析连接与外连接的区别
一对多关系,A一(主表),B多(子表),主表的一条记录对应子表的多条记录
图1图2
两个表要做连接,必须要有连接字段,而在表A和表B中连接字段是Aid和Bnamid,下图说明了连接之间关系图3
图3
(1)连接:
利用连接(等值)就可获取蓝色的公共部分C,即图3中的数据集C,结果集为如下:
只显示主表与子表有关联的记录,一个主表记录可能有多个子表记录(即在生成的中间表中,主表数据一般重复出现,所以查询出来的记录数根据每个主表记录有多少个子表记录而定,下同)
图4
其实select*fromAjoinBonA.Aid=B.Bnamid;等价于select*fromA,BwhereA.Aid=B.Bnamid;
注:
非等值连接主要的话是针对一个围来查询数据,自连接主要就是把1表堪称两表来用
(2)外连接:
分为左外连接(leftjoin)与右外连接(rightjoin)
左外连接即公共显示的蓝色部分C1+显示黄色的记录集A1,显示语句等价于select*fromA,BwhereA.Aid=B.Bnamid(+);
不但显示主表与子表有关联的记录,还显示主表与子表没有关联的主表记录
图5
右外连接即公共显示的蓝色部分C1+显示绿色的B1,显示语句等价于select*fromA,BwhereA.Aid(+)=B.Bnamid;
显示子表在主表有关联的记录,还显示子表与主表没有关联的子表记录
图6
表A和表B情况是相对的,以上实验都是A在左边的情况,其实AleftjoinB与BrightjoinA的情况的结果集是一样的。
自己的总结:
两表之间,只要有关联,不管以什么关系存在,都可能有对方关联或被关联不到的数据,这就是区分外连接的关键,数据的展示以关联的一方为准,被关联的可能重复被关联
以哪个表为准,就显示这个表的全部信息,抛去另一个表独有的部分
这是仅仅的技术层面,至于要以哪个表为准,要看业务逻辑的需要,哪个表的独有部分是我们更想要的,这时候,表之间的对应关系才更重要点,这是业务问题
利用关键性的数据库字段连接,才能更好地关联
8.SQL何时使用外连接
所谓外连接,就是表与表有条件的拼接,连接是连接条件所列字段,(比如a.recorder=b.userid中的recorder与userid)有值且满足表达式的记录才拼接成功并显示,外的左外,连接条件是给右表说的,连接表达式成立的记录与左表拼接,不成立的行不显示,不管拼接表达式是否成立,左表照常显示,
连接条件不受限制,并不是必须有主表,也可以是和主表连接的其他表组成连接条件
需要查找两表同时存在的数据,使用连接,需要查找两表中一表存在,另一表不存在的时候使用外连接。
SELECTT1.C1,T2.CX,T3.*--如果没有要求特别显示哪个字段,则所有表的字段都显示
FROMTAB1T1
INNERJOINTAB2T2ON(T1.C1=T2.C2)
LEFTJOINTAB3T3ON(T1.C1=T2.C3)--不管和哪个表组成连接条件,只要表达式成立的记录,才能和主表拼接并显示。
LEFTJOINTAB4T4ON(T3.C2=T4.C3);
比如有tableA,tableB,tableA和tableB是一对多
需求:
根据tableB的某写字段,查询出tableA
分析:
如果此时使用则相应的语句是:
selecta.*fromtableAa,tableBbwherea.id=tableB.aidandb.code='4401'
此时返回的结果是tableA在tableB有子数据的部分数据,而如果表tableA中的某条数据,在表tableB中不存在子数据,此时是查询不出来!
如果使用的是外连接,则相应的语句如下:
selecta.*fromtableAa leftjointableBbona.id=b.aidandb.code='4401';
此时返回的结果是tableA中的全部数据,而且有重复数出现,则应该用distinct过滤,语句如下:
selectdistincta.*fromtableAa leftjointableBbona.id=b.aidandb.code='4401';
联接查询可以连接两个或两个以上的表,参与联接的表的地位是平等的,
而外联接中参与联接的表有主从之分.以主表的每行数据去匹配从表的数据列,符合条件的数据将直接返回到结果集中,不符合的用NULL(空值)填充后再返回到结果集中.
介绍2
连接的查询结果都是满足连接条件的元组。
但有时我们也希望输出那些不满足连接条件的元组信息。
比如,
有学生表与选课表
我们想知道每个学生的选课情况(每个学生有唯一的学号),包括已经选课的学生(这部分学生的学号在学生表中有,在选课表中也有,是满足连接条件的),也包括没有选课的学生(这部分学生的学号在学生表中有,但在选课表中没有,不满足连接条件),这时就需要使用外连接。
外连接是只限制一表中的数据必须满足连接条件,而另一表中的数据可以不满足连接条件的连接方式。
3种外连接:
1)左外连接(LEFTOUTERJOIN)
如果在连接查询中,连接管子左端的表中所有的元组都列出来,并且能在右端的表中找到匹配的元组,那么连接成功。
如果在右端的表中,没能找到匹配的元组,那么对应的元组是空值(NULL)。
这时,查询语句使用关键字LEFTOUTERJOIN,也就是说,左外连接的含义是限制连接关键字右端的表中的数据必须满足连接条件,而不关左端的表中的数据是否满足连接条件,均输出左端表中的容。
例如:
要查询所有学生的选课情况,包括已经选课的和还没有选课的学生,查询语句为
SELECT学生表.学号,,班级,课程号,成绩
FROM学生表LEFTOUTERJOIN选课表ON学生表.学号=选课表.学号
左外连接查询中左端表中的所有元组的信息都得到了保留。
2)右外连接(RIGHTOUTERJOIN)
右外连接与左外连接类似,只是右端表中的所有元组都列出,限制左端表的数据必须满足连接条件,而不管右端表中的数据是否满足连接条件,均输出表中的容。
例如:
同上例容,查询语句为
SELECT学生表.学号,,班级,课程号,成绩
FROM学生表RIGHTOUTERJOIN选课表ON学生表.学号=选课表.学号
右外连接查询中右端表中的所有元组的信息都得到了保留。
3)全外连接(FULLOUTERJOIN)
全外连接查询的特点是左、右两端表中的元组都输出,如果没能找到匹配的元组,就使用NULL来代替。
例如:
同左外连接例子容,查询语句为
SELECT学生表.学号,,班级,课程号,成绩
FROM学生表FULLOUTERJOIN选课表ON学生表.学号=选课表.学号
全外连接查询中所有表中的元组信息都得到了保留。
答案
你首先是要搞清楚外连接和连接的概念之后就很容易进行判断了,你要将两个表匹配的记录都选取出来那么就是连接,你要将除了两表匹配之外还需要其中某一个表不匹配的记录,那么就用外连接,是左还是右取决于那个表是放在左边还是右边。
简单说就是以谁为准就用谁!
以左数据为准去找满足条件的右数据,就用左外连;以右数据为准去找满足条件的左数据,就用右外连;
连接:
取的两个表的(有能连接的字段),的交集,即字段相同的。
利用连接可获取两表的公共部分的记录
左外连接就是以A表学生数据为准,去找B表容或合并出另一个容。