zoukankan      html  css  js  c++  java
  • 数据库表的连接(Left join , Right Join, Inner Join)用法详解

    Left Join, Inner Join 的相关内容,非常实用,对于理解原理和具体应用都很有帮助!

    left join 是left outer join的简写,left join默认是outer属性的。
    Inner Join
    Inner Join 逻辑运算符返回满足第一个(顶端)输入与第二个(底端)输入联接的每一行。这个和用select查询多表是一样的效果,所以很少用到;
    outer join则会返回每个满足第一个(顶端)输入与第二个(底端)输入的联接的行。它还返回任何在第二个输入中没有匹配行的第一个输入中的行。关键就是后面那句,返回的多一些。所以通常意义上的left join就是left outer join

    一.先看一些最简单的例子

    例子

    Table A
    aid   adate
    1      a1
    2      a2
    3      a3

    TableB

    bid bdate
    1    b1
    2   b2
    4    b4
    两个表a,b相连接,要取出id相同的字段
    select * from a inner join b on a.aid = b.bid这是仅取出匹配的数据.
    此时的取出的是:
    1 a1 b1
    2 a2 b2

    那么left join 指:
    select * from a left join b on a.aid = b.bid
    首先取出a表中所有数据,然后再加上与a,b匹配的的数据
    此时的取出的是:
    1 a1 b1
    2 a2 b2
    3 a3 空字符

    同样的也有right join
    指的是首先取出b表中所有数据,然后再加上与a,b匹配的的数据
    此时的取出的是:
    1 a1 b1
    2 a2 b2
    4 空字符 b4

    LEFT JOIN 或 LEFT OUTER JOIN。
    左向外联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值

    二. 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 数据类型数据的字段,将会发生错误。

    三.相关的复杂的解释和实例

    简介: 外部连接和自联接 inner join(等值连接) 只返回两个表中联结字段相等的行 left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录 on 指定表间联结字段及其关系的等号 "=" 表达式, 返回 true 或 false. 当表达式返回 true 时, 则查询中包含该记录. ! 外部连接只能操作已存在于数据库中的数据
    update (ctarticle as a left join ctclass as c on a.classid = c.classid) left join cttag as b on a.articleid = b.articleid
    set tag=tag+' ', b.articleid=a.articleid, b.classid=a.classid, b.nclassid=a.nclassid
    where a.classid=23 and a.nclassid=0 and tagid is not null

    update (ctarticle as a left join (ctnclass as c left join ctclass as d on c.classid = d.classid) on a.nclassid = c.nclassid and a.classid = c.classid) left join cttag as b on a.articleid = b.articleid set tag=d.class+' '+c.nclass, b.articleid=a.articleid, b.classid=a.classid, b.nclassid=a.nclassid where a.classid=23 and a.nclassid=197;

    更新操作
    左连接中数据的筛选
    insert into cttag(articleid,classid,nclassid) select a.articleid,a.classid,a.nclassid from ctarticle a left join cttag b on a.articleid=b.articleid where b.articleid is null

    //本语句功能为, 显示主表的全部内容, 插入数据到副表中没有的数据
    //主要作用为: 让数据减少冗余

    上例中的延续
    select a.*, b.*, c.*, d.* from cttag as d left join ((ctarticle as a left join ctclass as b on a.classid=b.classid) left join ctnclass as c on a.nclassid=c.nclassid) on d.articleid=a.articleid;

    显示文章表中的全部, 调用类别表中的栏目
    select a.*, b.*, c.* from (ctarticle a left join ctclass b on a.classid=b.classid) left join ctnclass c on a.nclassid=c.nclassid

    //作用, 有时在文章表中包含了在个别类别表中没有的数据, 用这个语法可以读出文章表的全部数据
    //a 为 文章表, b 为主类别, c 为子类别

    同上例, 选择追加数据时加上空格
    insert into cttag(articleid,classid,nclassid,tag) select a.articleid,a.classid,a.nclassid,d.class+' '+c.nclass
    from (ctarticle as a left join (ctnclass c left join ctclass d on c.classid=d.classid) on a.classid=c.classid and a.nclassid=c.nclassid) left join cttag as b on a.articleid = b.articleid where a.classid=4 and a.nclassid=154;

    连接n个表, 并追加数据到其中一个表, n=4
    insert into cttag(articleid,classid,nclassid,tag) select a.articleid,a.classid,a.nclassid,d.class+c.nclass
    from (ctarticle as a left join (ctnclass c left join ctclass d on c.classid=d.classid) on a.classid=c.classid and a.nclassid=c.nclassid) left join cttag as b on a.articleid = b.articleid where a.classid=1 and a.nclassid=1;

    //解读
    插入到 表2(栏1,栏2,栏3,栏4)
    选择 别名a.栏1, 别名a.栏2, 别名a.栏3, 别名d.栏4 加上 别名c.栏5
    从 (表1 别名a 左连接 (表3 别名c 左连接 表4 别名d 在 别名c.栏2 等于 别名d.栏2) 在 别名a.栏2 等于 别名c.栏2 和 别名a.栏3=别名c.栏3) 左连接 表2 别名b 在 别名a.栏1 等于 别名b.栏1 在那里 别名a.栏2=1 和 别名a.栏3=1

    连接两个表, 并追加数据到其中一个表
    insert into cttag(articleid,classid,nclassid)
    select a.articleid,a.classid,a.nclassid
    from ctarticle as a left join cttag as b on a.articleid = b.articleid where a.classid=1 and a.nclassid=1;

    //解读
    插入到 表2(栏1,栏2,栏3)
    选择 别名a.栏1, 别名a.栏2, 别名a.栏3
    从 表1 别名a 左连接 表2 别名b 在 别名a.栏1 等于 别名b.栏1 在那里 别名a.栏4=1 和 别名a.栏5=1

    左连接

    同步两表的数据
    update ctarticle a inner join cttag b on a.articleid = b.articleid set b.classid=a.classid, b.nclassid=a.nclassid;

    //解读
    更新 表1 别名a 联接 表2 别名2 在 别名a.栏1 等于 别名b.栏1 设置 别名b.栏2 更新为 别名a.栏2, 别名b.栏3 更新为 别名a.栏3

    右外连接
    select a.*, b.* from bunclass a right join ctclass b on a.classid=b.classid where a.nclassid=20

    查询别名 a,b 表, 只匹配 b 表中的内容.

    添加数据到连接表之一
    insert into cttag ( tag, articleid ) select top 1 b.tag, a.articleid from ctarticle as a left join cttag as b on a.articleid = b.articleid where a.articleid order by a.articleid desc;

    变通中的用法二
    insert into bureply
    select b.*, a.classid, a.nclassid
    from article as a inner join reply as b on a.articleid = b.articleid
    where classid=50;

    实际应用中的变通
    insert into butag ( tag, articleid, classid, nclassid)
    select b.tag, a.articleid, a.classid, a.nclassid
    from article as a inner join tag as b on a.articleid = b.articleid
    where classid=24;


    添加数据到其他表
    insert into butag ( tag, articleid )
    select b.tag, a.articleid
    from article as a inner join tag as b on a.articleid = b.articleid
    where a.articleid<>false;

    //解读
    添加到 接收表(列1,列2)
    选择 别名b.列1, 别名a.列2
    从 表1 表名a 联接 表2 表名b 在 别名a.列c 等于 别名b.列c
    在哪里 别名a.列c 不等于 没有

    实际应用中的变通
    select b.tag, a.articleid, a.classid, a.nclassid
    from article as a inner join tag as b on a.articleid = b.articleid
    where a.classid=24;

    查询
    select b.tag, a.articleid
    from article as a inner join tag as b on a.articleid = b.articleid
    where a.articleid<>false;

    //解读
    选择 别名b.列, 别名a.列
    从 表1 别名a 联接 表2 别名b 在 别名a.列c = 别名b.列c
    在哪里 别名a.列c 不等于 没有
    注: as 不是必要

  • 相关阅读:
    linux常用命令
    mysql 开发基础系列20 事务控制和锁定语句(上)
    sql server 性能调优之 资源等待 CXPACKET
    mysql 开发基础系列19 触发器
    mysql 开发基础系列18 存储过程和函数(下)
    mysql 开发基础系列17 存储过程和函数(上)
    sql server 性能调优之 资源等待PAGEIOLATCH
    mysql 开发基础系列16 视图
    mysql 开发基础系列15 索引的设计和使用
    sql server 性能调优之 当前用户请求分析 (1)
  • 原文地址:https://www.cnblogs.com/weblogical/p/1974585.html
Copyright © 2011-2022 走看看