数据库左连接 右连接 内连接

上一篇 / 下一篇  2013-03-21 12:46:01

左连接和右连接的区别

举例说明left/right/inner join之间的区别(转)

inner join,left join,right join,full join 的区别,用例子说明
 

[TEST@ORA1] SQL>select * from a;

编号 姓名
---- ----------
1000 张三
2000 李四
3000 王五

[TEST@ORA1] SQL>select * from b;

编号 商品
---- ----------
1000 电视机
2000 录像机
4000 自行车

[TEST@ORA1] SQL>set null 空值--这里为了显示方面我把NULL定义成了[空值]

[TEST@ORA1] SQL>select a.*,b.* from a inner join b on a.编号=b.编号;

编号 姓名       编号 商品
---- ---------- ---- ----------
1000 张三       1000 电视机
2000 李四       2000 录像机

[TEST@ORA1] SQL>select a.*,b.* from a left join b on a.编号=b.编号;

编号 姓名       编号 商品
---- ---------- ---- ----------
1000 张三       1000 电视机
2000 李四       2000 录像机
3000 王五       空值 空值

[TEST@ORA1] SQL>select a.*,b.* from a right join b on a.编号=b.编号;

编号 姓名       编号 商品
---- ---------- ---- ----------
1000 张三       1000 电视机
2000 李四       2000 录像机
空值 空值       4000 自行车

[TEST@ORA1] SQL>select a.*,b.* from a full join b on a.编号=b.编号;

编号 姓名       编号 商品
---- ---------- ---- ----------
1000 张三       1000 电视机
2000 李四       2000 录像机
3000 王五       空值 空值
空值 空值       4000 自行车

================================

为了从两个或多个表中选出数据,一般使用表连接来实现这个功能。
   这里先介绍join(连接)的概念. 为此我们准备了两个试验用表: album(专辑表) 和 track(曲目表).
专辑表:包含200首来自Amazon的音乐CD的概要信息。
album(asin, title, artist, price, release, label, rank)
曲目表:每张专辑中的曲目(因为是音乐CD,所以也可叫歌曲)的详细信息。
track(album, dsk, posn, song)
SQL短语 FROM album JOIN track ON album.asin=track.album 表示连接album和track表。
其中,album.asin表示专辑的惟一标识号,track.album表示曲目表中和专辑关联的专辑号。
连接后,得到一个临时表,该临时表中每条记录包含的字段由两部分组成,
除了专辑表中的对应字段album(title, artist ...),还包含曲目表的所有字段track(album, disk, posn and song)。
有了这张临时表,很多查询就容易实现了。
看看一些具体的实例,
一、列出歌名为'Alison'的专辑名称和作者
SELECT title, artist
FROM album JOIN track
ON (album.asin=track.album)
WHERE song = 'Alison'
显然,歌名、专辑名称和作者分别在两个表中,必需使用表连接来完成这个查询。
二、哪个artist录制了歌曲'Exodus'
SELECT artist
FROM album JOIN track ON (asin=album)
WHERE song = 'Exodus'
用作连接的两个字段asin,album因为在两个表中都是惟一的,所以不一定要加表名作为前缀。
但为了方便理解,建议使用前缀,形如:album.asin=track.album
三、列出曲目表中所有属于'Blur'专辑的歌曲
SELECT song
FROM album JOIN track ON (asin=album)
WHERE title = 'Blur'
如果我们把 album JOIN track ON (asin=album) 看成一个临时表的话,join的概念就很好理解了。
以上我们介绍了表连接,更确切的说是inner joins內连接.
內连接仅选出两张表中互相匹配的记录.因此,这会导致有时我们需要的记录没有包含进来。
为更好的理解这个概念,我们介绍两个表作演示。苏格兰议会中的政党表(party)和议员表(msp)。
party(Code,Name,Leader)
Code: 政党代码
Name: 政党名称
Leader: 政党领袖
msp(Name,Party,Constituency)
Name: 议员名
Party: 议员所在政党代码
Constituency: 选区
在介绍左连接、右连接和全连接前,有一个数据库中重要的概念要介绍一下,即空值(NULL)。
有时表中,更确切的说是某些字段值,可能会出现空值, 这是因为这个数据不知道是什么值或根本就不存在。空值不等同于字符串中的空格,也不是数字类型的0。因此,判断某个字段值是否为空值时不能使用=,& lt;>这些判断符。必需有专用的短语:IS NULL 来选出有空值字段的记录,同理,可用 IS NOT NULL 选出不包含空值的记录。
例如:下面的语句选出了没有领导者的政党。(不要奇怪,苏格兰议会中确实存在这样的政党)
SELECT code, name FROM party
WHERE leader IS NULL
  又如:一个议员被开除出党,看看他是谁。(即该议员的政党为空值)
SELECT name FROM msp
WHERE party IS NULL
  好了,让我们言归正传,看看什么叫左连接、右连接和全连接。
  A left join(左连接)包含所有的左边表中的记录甚至是右边表中没有和它匹配的记录。
  同理,也存在着相同道理的 right join(右连接),即包含所有的右边表中的记录甚至是左边表中没有和它匹配的记录。
而full join(全连接)顾名思义,左右表中所有记录都会选出来。
  讲到这里,有人可能要问,到底什么叫:包含所有的左边表中的记录甚至是右边表中没有和它匹配的记录。
  我们来看一个实例:
SELECT msp.name, party.name
FROM msp JOIN party ON party=code
  这个是我们上一节所学的Join(注意:也叫inner join),这个语句的本意是列出所有议员的名字和他所属政党。
  很遗憾,我们发现该查询的结果少了两个议员:Canavan MSP, Dennis。为什么,因为这两个议员不属于任何政党,即他们的政党字段(Party)为空值。那么为什么不属于任何政党就查不出来了?这是因为空值在作怪。因为议员表中政党字段(Party)的空值在政党表中找不到对应的记录作匹配,即FROM msp JOIN party ON party=code 没有把该记录连接起来,而是过滤出去了。
  在该短语中,msp在Join的左边,所有称为左表。party在Join的右边,所有称为右表。
  现在再看看这句话,“包含所有的左边表中的记录甚至是右边表中没有和它匹配的记录”,意思应该很明白了吧。执行下面这个语句,那两个没有政党的议员就漏不了了。
SELECT msp.name, party.name
FROM msp LEFT JOIN party ON party=code
  关于右连接,看看这个查询就明白了:
SELECT msp.name, party.name
FROM msp RIGHT JOIN party ON msp.party=party.code
  这个查询的结果列出所有的议员和政党,包含没有议员的政党,但不包含没有政党的议员。 那么既要包含没有议员的政党,又要包含没有政党的议员该怎么办呢,对了,全连接(full join)。
SELECT msp.name, party.name
FROM msp FULL JOIN party ON msp.party=party.code

===================

JOIN返回”first_table”中所有的行尽管在” second_table”中没有相匹配的数据。

RIGHT JOIN返回”second_table”中所有的行尽管在”first_table”中没有相匹配的数据。

INNER JOIN返回的结果集是两个表中所有相匹配的数据。


没听明白?请继续看下文分解。

2,分解:

还是用一个例子来的痛快些。。。


declare @a table(a int,b int)
declare @b table(a int,b int)

insert @a values(1,1)
insert @a values(2,2)
insert @b values(1,1)
insert @b values(3,3)

--左:
select * from @a Aa left join @b Bb on Aa.a=Bb.a
--右:
select * from @a Aa right join @b Bb on Aa.a=Bb.a
--内
select * from @a Aa join @b Bb on Aa.a=Bb.a
--外:
select * from @a Aa full join @b Bb on Aa.a=Bb.a
--完全
select * from @a,@b
-- cross join
select * from @a Aa cross join @b Bb


cross join 是笛卡儿乘积就是一张表的行数乘以另一张表的行数
left join 第一张表的连接列在第二张表中没有匹配是,第二张表中的值返回null
right join 第二张表的连接列在第一张表中没有匹配是,第一张表中的值返回null
full join 返回两张表中的行 left join+right join
inner join 只返回两张表连接列的匹配项

==========================

表A记录如下:
aID        aNum
1           a20050111
2           a20050112
3           a20050113
4           a20050114
5           a20050115

表B记录如下:
bID        bName
1            2006032401
2           2006032402
3           2006032403
4           2006032404
8           2006032408

实验如下:
1.    left join
sql语句如下:
SELECT * FROM A
LEFT JOIN B
ON A.aID = B.bID

结果如下:
aID        aNum                   bID           bName
1            a20050111         1               2006032401
2            a20050112         2              2006032402
3            a20050113         3              2006032403
4            a20050114         4              2006032404
5            a20050115         NULL       NULL
(所影响的行数为 5 行)

结果说明:
        left join是以A表的记录为基础的,A可以看成左表,B可以看成右表,left join是以左表为准的.
换句话说,左表(A)的记录将会全部表示出来,而右表(B)只会显示符合搜索条件的记录(例子中为: A.aID = B.bID).
B表记录不足的地方均为NULL.

2.    right join
sql语句如下:
SELECT * FROM A
RIGHT JOIN B
ON A.aID = B.bID

结果如下:
aID        aNum                   bID           bName
1            a20050111         1               2006032401
2            a20050112         2              2006032402
3            a20050113         3              2006032403
4            a20050114         4              2006032404
NULL    NULL                8              2006032408
(所影响的行数为 5 行)

结果说明:
        仔细观察一下,就会发现,和left join的结果刚好相反,这次是以右表(B)为基础的,A表不足的地方用NULL填充.

3.inner join
sql语句如下:
SELECT * FROM A
INNERJOIN B
ON A.aID = B.bID

结果如下:
aID        aNum                   bID           bName
1            a20050111         1               2006032401
2            a20050112         2              2006032402
3            a20050113         3              2006032403
4            a20050114         4              2006032404

结果说明:
        很明显,这里只显示出了 A.aID = B.bID的记录.这说明inner join并不以谁为基础,它只显示符合条件的记录.


    LEFT JOIN操作用于在任何的 FROM 子句中,组合来源表的记录。使用 LEFT JOIN 运算来创建一个左边外部联接。左边外部联接将包含了从第一个(左边)开始的两个表中的全部记录,即使在第二个(右边)表中并没有相符值的记录。

语法:
FROM table1 LEFT JOIN table2 ON table1.field1 compopr table2.field2

说明:
① table1, table2参数用于指定要将记录组合的表的名称。
② field1, field2参数指定被联接的字段的名称。且这些字段必须有相同的数据类型及包含相同类型的数据,但它们不需要有相同的名称。
③ compopr参数指定关系比较运算符:"=", "<", ">", "<=", ">=" 或 "<>"。
④  如果在INNER JOIN操作中要联接包含Memo 数据类型或 OLE Object 数据类型数据的字段,将会发生错误。 LEFT JOIN 等同于LEFT OUTER JOIN,RIGHT JOIN 等同于RIGHT OUTER JOIN,FULL JOIN 等同于FULL OUTER JOIN

==============

JOIN: 如果表中有至少一个匹配,则返回行
LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行
RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行
FULL JOIN: 只要其中一个表中存在匹配,就返回行



Left Join / Right Join /inner join相关

关于左连接和右连接总结性的一句话:

左连接where只影向右表,右连接where只影响左表。

Left Join

select * from tbl1 Left Join tbl2 where tbl1.ID = tbl2.ID

左连接后的检索结果是显示tbl1的所有数据和tbl2中满足where 条件的数据。

简言之 Left Join影响到的是右边的表

Right Join

select * from tbl1 Right Join tbl2 where tbl1.ID = tbl2.ID

检索结果是tbl2的所有数据和tbl1中满足where 条件的数据。

简言之 Right Join影响到的是左边的表。

inner join

select * FROM tbl1 INNER JOIN tbl2 ON tbl1.ID = tbl2.ID

功能和 select * from tbl1,tbl2 where tbl1.id=tbl2.id相同。

其他相关资料

1 .WHERE子句中使用的连接语句,在数据库语言中,被称为隐性连接。INNER JOIN……ON子句产生的连接称为显性连接。(其他JOIN参数也是显性连接)WHERE 和INNER JOIN产生的连接关系,没有本质区别,结果也一样。但是!隐性连接随着数据库语言的规范和发展,已经逐渐被淘汰,比较新的数据库语言基本上已经抛弃了隐性连接,全部采用显性连接了。

2 .无论怎么连接,都可以用join子句,但是连接同一个表的时候,注意要定义别名,否则产生错误!

a> inner join:理解为“有效连接”,两张表中都有的数据才会显示left join:理解为“有左显示”,比如on a.field=b.field,则显示a表中存在的全部数据及a\\b中都有的数据,A中有、B没有的数据以null显示

b> right join:理解为“有右显示”,比如on a.field=b.field,则显示B表中存在的全部数据及a\\b中都有的数据,B中有、A没有的数据以null显示

c> full join:理解为“全连接”,两张表中所有数据都显示,实际就是inner +(left-inner)+(right-inner)

3 .join可以分主次表 外联接有三种类型:完全外联,左联,右联.
完全外联包含两张表的所有记录.
左联是以左边的表为主,右边的为辅,右联则相反

4.一般要使得数据库查询语句性能好点遵循一下原则:

在做表与表的连接查询时,大表在前,小表在
不使用表别名,通过字段前缀区分不同表中的字段
查询条件中的限制条件要写在表连接条件前
尽量使用索引的字段做为查询条件


全部脚印不留脚印
 
 

TAG:

wuwoyiran的个人空间 引用 删除 wuwoyiran   /   2013-03-21 15:22:42
写的很清楚!
wuwoyiran的个人空间 引用 删除 wuwoyiran   /   2013-03-21 15:22:23
5
 

评分:0

我来说两句

日历

« 2024-05-12  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 4866
  • 日志数: 10
  • 建立时间: 2012-09-28
  • 更新时间: 2013-03-21

RSS订阅

Open Toolbar