您的位置:首页 > 数据库

SQL 连接 JOIN 例解。(左连接,右连接,全连接,内连接,交叉连接,自连接)

2013-06-11 21:51 330 查看


假设有如下表:



一个为投票主表,一个为投票者信息表~记录投票人IP及对应投票类型,左右连接实际说是我们联合查询的结果以哪个表为准~
1:如右接连 right join 或 right outer join:



我们以右边voter表为准,则左表(voteMaster)中的记录只有当其ID在右边(voter)中存在时才会显示出来,如上图,左边中ID为3.4.5.6因为这些ID右表中没有相应记录,所以没有显示!
2:因此我们自然能理解左连接 left join 或者 left outer join



可见,现在右边中ID在中存在时才会显示,当右边中没有相应数据时则用NULL代替!
3:全连接 full join 或者 full outer join,为二个表中的数据都出来,这里演示效果与上一样!
4:内连接 inner join 或者 join;它为返回字段ID同时存在于表voteMaster 和 voter中的记录



5:交叉连接(完全连接)cross join 不带 where 条件的
没有 WHERE 子句的交叉联接将产生联接所涉及的表的笛卡尔积。第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小。(table1和table2交叉连接产生6*3=18条记录)



等价select vm.id,vm.voteTitle,vt.ip from voteMaster as vm,voter as vt

6:自连接。在这里我用我前段时间一个电力项目中的例子(改造过)
如下表:



这是一个部门表,里面存放了部门及其上级部门,但都放在同一张表中,我们假设现在需要用SQL查询出各部门及其上级部门!就如何做,
当然,不用自连接也一样,可以如下:



我们达到预期目的!在这个查询中使用了一个子查询完成对上级部门名的查询,如果使用自连接,那么结构上感觉会清晰很多。



是不是也同样完成了功能呢,这里除了使用自连接外,还使用了左连接,因为省电力没有上级部门,他是老大,如果使用内连接,就会把这条记录过滤掉,因为没有和他匹配的上级部门。
自连接用的比较多的就是对权形结构的查询!类似上表!

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

从两个或更多个表中组合数据的过程称为连接表。数据库管理程序从指定的表中形成行的所有组合。对于每个组合,它都测试连接条件。连接条件是带有一些约束的搜索条件。有关约束的列表,参考 SQL Reference。

  注意:连接条件涉及的列的数据类型不必相同;然而,这些数据类型必须相容。计算连接条件的方式与计算其他搜索条件的方式相同,并且使用相同的比较规则。

  如果未指定连接条件,则返回在 FROM 子句中列出的表中行的所有组合,即使这些行可能完全不相关。该结果称为这两个表的交叉积。

  本节中的示例基于下面两个表。这两个表只是样本数据库中表的简化形式,在样本数据库中并不存在。这tb两个表一般用来概述关于连接的重点。 SAMP_STAFF 列出未作为合同工雇用的雇员的姓名以及这些雇员的职务说明,而 SAMP_PROJECT 则列出雇员(合同工和全职人员)的姓名以及这些雇员所参与的项目。

  这些表如下:

  图 5. SAMP_PROJECT 表





  图 6. SAMP_STAFF 表





  下列示例产生两个表的交叉积。因未指定连接条件,所以给出了行的所有组合:

   SELECT SAMP_PROJECT.NAME,
      SAMP_PROJECT.PROJ, SAMP_STAFF.NAME, SAMP_STAFF.JOB
    FROM SAMP_PROJECT, SAMP_STAFF

  此语句产生下列结果:





  两个主要的连接类型是内连接和外连接。到目前为止,所有示例中使用的都是内连接。tb内连接只保留交叉积中满足连接条件的那些行。如果某行在一个表中存在,但在另一个表中不存在,则结果表中不包括该信息。

  下列示例产生两个表的内连接。该内连接列出分配给某个项目的全职雇员信息:

   SELECT SAMP_PROJECT.NAME,
      SAMP_PROJECT.PROJ, SAMP_STAFF.NAME, SAMP_STAFF.JOB
    FROM SAMP_PROJECT, SAMP_STAFF
    WHERE SAMP_STAFF.NAME = SAMP_PROJECT.NAME

  或者,也可以指定如下内连接:

   SELECT SAMP_PROJECT.NAME,
      SAMP_PROJECT.PROJ, SAMP_STAFF.NAME, SAMP_STAFF.JOB
    FROM SAMP_PROJECT INNER JOIN SAMP_STAFF
     ON SAMP_STAFF.NAME = SAMP_PROJECT.NAME

  结果是:



  注意:该内连接的结果由右表和左表中姓名列的值匹配的行组成- 'Haas' 和 'Thompson' 都包括在列出所有全职雇员的 SAMP_STAFF 表中以及列出分配给某个项目的专职和合同雇员的 SAMP_PROJECT 表中。

  外连接是内连接和左表和/或右表中未包括内连接中的那些行的并置。当对两个表执行外连接时,可任意将一个表指定为左表而将另一个表指定为右表。外连接有三种类型:

  左外连接包括内连接和左表中未包括在内连接中的那些行。

  右外连接包括内连接和右表中未包括在内连接中的那些行。

  全外连接包括内连接以及左表和右表中未包括在内连接中的行。
  使用 SELECT 语句来指定要显示的列。在 FROM 子句中,列出后跟关键字 LEFT OUTER JOIN、RIGHT OUTER JOIN 或 FULL OUTER JOIN 的第一个表的名称。接着需要指定后跟 ON 关键字的第二个表。在 ON 关键字后面,指定表示要连接的表之间关系的连接条件。

  在下列示例中,将 SAMP_STAFF 指定为右表,而 SAMP_PROJECT 则被指定为左表。通过使用 LEFT OUTER JOIN,列出所有全职和合同雇员(在 SAMP_PROJECT 中列出)的姓名和项目编号,如果是全职雇员(在 SAMP_STAFF 中列出),还列出这些雇员的职位:

   SELECT SAMP_PROJECT.NAME, SAMP_PROJECT.PROJ,
      SAMP_STAFF.NAME, SAMP_STAFF.JOB
    FROM SAMP_PROJECT LEFT OUTER JOIN SAMP_STAFF
     ON SAMP_STAFF.NAME = SAMP_PROJECT.NAME

  此语句产生下列结果:





  所有列中都具有值的那些行是该内连接的结果。这些都是满足连接条件的行: 'Haas' 和 'Thompson' 既在 SAMP_PROJECT(左表)中列出又在 SAMP_STAFF(右表)中列出。对于不满足连接条件的行,右表的列上出现空值: 'Lutz' 和 'Walker' 都是在 SAMP_PROJECT 表中列出的合同雇员,因而未在 SAMP_STAFF 表中列出。注意:左表中的所有行都包括在结果集中。

  在下一个示例中,将 SAMP_STAFF 指定为右表而 SAMP_PROJECT 则被指定为左表。通过使用 RIGHT OUTER JOIN 列出所有专职雇员(在 SAMP_STAFF 中列出)的姓名和工作职位,如果将这些雇员分配给了某个项目(在 SAMP_PROJECT 中列出),还列出他们的项目编号:

   SELECT SAMP_PROJECT.NAME,
      SAMP_PROJECT.PROJ, SAMP_STAFF.NAME, SAMP_STAFF.JOB
    FROM SAMP_PROJECT RIGHT OUTER JOIN SAMP_STAFF
     ON SAMP_STAFF.NAME = SAMP_PROJECT.NAME

  结果为:





  象在左外连接中一样,所有列中都具有值的那些行是内连接的结果。这些都是满足连接条件的行: 'Haas'和'Thompson'既在 SAMP_PROJECT(左表)中列出又在 SAMP_STAFF(右表)中列出。对于不满足连接条件的行,右表的列上出现空值: 'Lucchessi'和'Nicholls'都是未分配项目的专职雇员。虽然他们在 SAMP_STAFF 中列出,但未在 SAMP_PROJECT 中列出。注意:右表中的所有行都包括在结果集中。

  下一个示例对 SAMP_PROJECT 表和 SAMP_STAFF 表使用 FULL OUTER JOIN。该示例列出所有专职雇员(包括未分配项目的雇员)和合同雇员的姓名:

   SELECT SAMP_PROJECT.NAME, SAMP_PROJECT.PROJ,
      SAMP_STAFF.NAME, SAMP_STAFF.JOB
    FROM SAMP_PROJECT FULL OUTER JOIN SAMP_STAFF
     ON SAMP_STAFF.NAME = SAMP_PROJECT.NAME

  结果为:





  此结果包括左外连接、右外连接以及内连接。列出所有专职雇员和合同雇员。正如左外连接和右外连接一样,对于不满足连接条件的值,相应列中出现空值。 SAMP_STAFF 和 SAMP_PROJECT 中的每一行都包括在结果集中。
SQL语句实例:
(1) 右连接
select * from ry_jbxx, ry_rxzp where ry_jbxx.gmsfhm(+) = ry_rxzp.gmsfhm
等价
select * from ry_jbxx right OUTER JOIN ry_rxzp on ry_jbxx.gmsfhm = ry_rxzp.gmsfhm
(2) 左连接
select * from ry_jbxx, ry_rxzp where ry_jbxx.gmsfhm = ry_rxzp.gmsfhm(+)
等价
select * from ry_jbxx LEFT OUTER JOIN ry_rxzp on ry_jbxx.gmsfhm = ry_rxzp.gmsfhm

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

本文主要列举两张和三张表来讲述多表连接查询。
新建两张表:
表1:student 截图如下:



表2:course 截图如下:



(此时这样建表只是为了演示连接SQL语句,当然实际开发中我们不会这样建表,实际开发中这两个表会有自己不同的主键。)
一、外连接
外连接可分为:左连接、右连接、完全外连接。
1、左连接 left join 或 left outer join
SQL语句:select * from student left join course on student.ID=course.ID
执行结果:



左外连接包含left join左表所有行,如果左表中某行在右表没有匹配,则结果中对应行右表的部分全部为空(NULL).
注:此时我们不能说结果的行数等于左表数据的行数。当然此处查询结果的行数等于左表数据的行数,因为左右两表此时为一对一关系。
2、右连接 right join 或 right outer join
SQL语句:select * from student right join course on student.ID=course.ID
执行结果:



右外连接包含right join右表所有行,如果左表中某行在右表没有匹配,则结果中对应左表的部分全部为空(NULL)。
注:同样此时我们不能说结果的行数等于右表的行数。当然此处查询结果的行数等于左表数据的行数,因为左右两表此时为一对一关系。
3、完全外连接 full join 或 full outer join
SQL语句:select * from student full join course on student.ID=course.ID
执行结果:



完全外连接包含full join左右两表中所有的行,如果右表中某行在左表中没有匹配,则结果中对应行右表的部分全部为空(NULL),如果左表中某行在右表中没有匹配,则结果中对应行左表的部分全部为空(NULL)。
二、内连接 join 或 inner join
SQL语句:select * from student inner join course on student.ID=course.ID
执行结果:



inner join 是比较运算符,只返回符合条件的行。
此时相当于:select * from student,course where student.ID=course.ID
三、交叉连接 cross join
1.概念:没有 WHERE 子句的交叉联接将产生连接所涉及的表的笛卡尔积。第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小。
SQL语句:select * from student cross join course
执行结果:



如果我们在此时给这条SQL加上WHERE子句的时候比如SQL:select * from student cross join course where student.ID=course.ID
此时将返回符合条件的结果集,结果和inner join所示执行结果一样。
四、两表关系为一对多,多对一或多对多时的连接语句
当然上面两表为一对一关系,那么如果表A和表B为一对多、多对一或多对多的时候,我们又该如何写连接SQL语句呢?
其实两表一对多的SQL语句和一对一的SQL语句的写法都差不多,只是查询的结果不一样,当然两表也要略有改动。
比如表1的列可以改为:
Sno Name Cno
表2的列可以改为:
Cno CName
这样两表就可以写一对多和多对一的SQL语句了,写法和上面的一对一SQL语句一样。
下面介绍一下当两表为多对多的时候我们该如何建表以及些SQL语句。
新建三表:
表A: student 截图如下:



表B: course 截图如下:



表C: student_course 截图如下:



一个学生可以选择多门课程,一门课程可以被多个学生选择,因此学生表student和课程表course之间是多对多的关系。
当两表为多对多关系的时候,我们需要建立一个中间表student_course,中间表至少要有两表的主键,当然还可以有别的内容。
SQL语句:select s.Name,C.Cname from student_course as sc left join student as s on s.Sno=sc.Sno left join course as c on c.Cno=sc.Cno
执行结果:



此条SQL执行的结果是学生选课的情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐