zoukankan      html  css  js  c++  java
  • 转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: 只要其中一个表中存在匹配,就返回行

  • 相关阅读:
    LA 3882
    Codeforces 161D
    spoj PARTIT
    uva 10496 Collecting Beepers
    uva 10130 SuperSale
    spoj 3885
    NWERC 2012 Problem I Idol
    NWERC 2012 Problem E Edge Case
    【USACO 1.3.2】修理牛棚
    【USACO 1.3.1】混合牛奶
  • 原文地址:https://www.cnblogs.com/9421/p/1652242.html
Copyright © 2011-2022 走看看