SQL多表查询(SQL 92 与SQL 99详解)

连接查询

Join表操作符对两个输入表进行了操作。连接有三种基本类型:交叉连接,内连接,外链接。这三种连接的区别是它们采用的逻辑查询处理步骤各部相同,每种连接都有一套不同的步骤。交叉连接只有一个步骤—笛卡尔积;内连接有两个步骤—笛卡尔积,过滤;外链接有三个步骤—笛卡尔积,过滤,添加外部行。

SQL语句的历史版本

		SQL89(比较多)         
		SQL92(标准,又称sql2)
		SQL99(标准,又称sql3)

就目前为止 , SQL多表查询可总结为两种标准 , 即 : SQL92标准和SQL99标准 ; 92标准相对与99标准来说 , 语句上比较冗杂 , 外连接不太容易识别 。但也有它的便捷之处。总之无论如何,接下来就是对这两种标准多表查询的详解

多表关联查询包括

        笛卡尔积
        等值关联查询
        非等值关联查询
        左外连接
        右外连接
        全外连接
        自连接

–SQL92 语法

笛卡尔积(将两张表的数据拼接在一起,总记录数为两张表记录量的乘积 ( 表*表 ) )

select * from emp e,dept d

等值连接 ( 在where后的条件为等值条件 , 即: “=” )

select * from emp t, dept d where t.deptno = d.deptno;

非等值连接 ( 在where后的条件为非等值条件 , 例如:> , < , >= , <= 等 )

select e.ename,s.grade from emp e, salgrade s where e.sal between s.losal and s.hisal;

自连接 ( 在where后的条件 , 用自身字段之间的关连作为条件 )

select e1.ename,e2.ename from emp e1,emp e2 where e1.mgr = e2.empno;

外连接 (在满足一张表的内容都显示的基础上,连接另外一张表,如果连接匹配则正常显示,连接不匹配,另外一张表补null)

select e.ename,d.dname from emp e, dept d where e.deptno = d.deptno(+) ;

–SQL 99 语法 :

语法形式 : select a.column,b.column from 表a 连接类型 JOIN 表b on 连接条件

交叉连接 (CROSS JOIN) : 可理解为92语法中的笛卡尔积

select * from emp cross join dept;

自然连接 (NATURAL JOIN):根据两张表中相同字段名称,进行等值连接

select * from emp natural join dept;

内连接 (INNER JOIN)(INNER关键字可以省略)
–(1)等值连接

select e.ename, d.dname
    from emp e
   INNER JOIN dept d
      on e.deptno = d.deptno
   where e.sal > 2000

–(2)非等值连接

  select e.ename, s.grade
    from emp e
   INNER JOIN salgrade s
      on e.sal between s.losal and s.hisal

–(3)自连接

    select e1.ename || '的上司是' || e2.ename
    from emp e1
   INNER JOIN emp e2
      on e1.mgr = e2.empno

外连接 (OUTER关键字可以省略)
–(1)LEFR OUTER JOIN(左外连接)

select * from emp e LEFT OUTER JOIN dept d on e.deptno = d.deptno

–(2)RIGHT OUTER JOIN(右外连接)

select * from emp e RIGHT OUTER JOIN dept d on e.deptno = d.deptno

–(3)FULL OUTER JOIN(全外连接)

select * from emp e FULL OUTER JOIN dept d on e.deptno = d.deptno

接下来详细讲解各种连接

交叉连接

交叉联接是一种最简单的联接,交叉联接只实现一个笛卡尔积即可。这一步就是对两张表进行操作,把它们联接起来,生成两者的笛卡尔积。也就是将一个输入表的每行和另一张表的每行进行匹配。如果一张表有n行,另一张表有m行,将得到m * n行。

ANSI SQL-99:Cross Join

ANSI SQL-92:在两张表间放置一个逗号

内连接(ANSI SQL-99标准提出来的概念)

–内连接(整合了ANSI SQL-92的等值连接,不等值连接,自连接)

   (1)
		--等值连接
  		--不等值连接
   (2)
  		--非自连接
   		--自连接

内连接要应用两个逻辑查询处理步骤:它首先像交叉联接一样,对两个输入表进行笛卡尔积运算:然后根据用户指定的谓词对结果进行过滤。和交叉联接一样,内联接也有两种标准语法。

ANSI SQL-99:Inner Join 或者 Join(由于内连接是默认的联接方式,所以也可以只写Join)

ANSI SQL-92:在两张表间放置一个逗号,在查询的where子句中写过滤条件。

强烈推荐使用Inner Join,因为假如你忘记写过滤条件(on),执行时SQL会报错。而如果使用SQL-92语法,则不会报错。那么这个内连接就变成交叉连接了! 而且实际开发中SQL语句会非常的复杂,写错的概率就很大了。

补充一下:

1.组合连接

有时候过滤条件不止一个,这时候就要用and来连接多个条件,这就叫做组合连接。例如:Table2表中定义了一个外键(col1和col2),引用了Table1表的col1和col2列,现在要写一个根据主外键关系来连接两个表的查询语句。该条件如下:

from table1 as t1
join table2 as t2
on t1.col1 = t2.col1 and t1.col2 = t2.col2

2.多表连接

一个联接表运算符只对两个表进行操作,而一条查询语句可以包含多个联接。通常,当FROM子句中包含多个表运算符时,表运算符在逻辑上是按从左到右的顺序处理的。也就是说,第一个表运算符的结果将作为第二个表运算符的输入,第二个表运算符的结果将作为第三个运算符左边的输入,以此类推。
外连接

外连接会应用内连接所应用的两个逻辑处理步骤(笛卡尔积和On过滤),此外还多一个外连接特有的第三步:添加外部行。

ANSI SQL-92:在原有等值连接的基础上加上左边或者右边加上(+),实现外连接查询

ANSI SQL-99:

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

解释:在外连接中,要把一个表标记为“保留的”表,可以在表名之间使用关键字LEFT OUT JOIN、RIGHT OUTER JOIN ,以及 FULL OUTER JOIN,其中 OUTER 失键字是可选的。 LEFT关键字表示左边表的行是保留的关键字表示右边表的行是保留的,而FULL 关键字则表示左右两边表的行都是保留的。外联接的第三个逻辑杏询处理步骤就是要识别保留表中按照ON条件在另一个表找不到与之匹配的那些行,再把这些行添加到联接 的前两个步骤生成的结果表中:对于来自联接的非保留表的那些列,追加的外部行中的这些列则用NULL作为占位符。

补充一下:自然连接:
自然连接是在两张表中寻找那些数据类型和列名都相同的字段,然后自动地将他们连接起来,并返回所有符合条件按的结果。

自然连接无需指定连接列,sql会检查两个表中是否相同名称的列,且假设他们在连接条件中使用,并且在连接条件中仅包含一个连接列。不允许使用on语句,不允许指定显示列,显示列只能用*表示(oracle环境下测 试的)。对于每种连接类型(除了交叉连接外),均可指定natural。


最后用下面例子来总结一下知识点:

---多表联合查询
  ---当需要获取的数据分布在多张表中使用多表联合查询
  ---SQL92方式
      ---笛卡尔积:将多个表的数据进行一一对应,所得到结果为多表的笛卡尔积.
                  ---结果数量为所有表数量的乘积
                  seelct * from emp,dept;
      ---等值链接
             ----先做表的笛卡尔积,然后筛选,筛选条件为等值筛选.
               ---查询员工的姓名,工作,薪资,部门名称
               select * from emp,dept where dept.deptno=emp.deptno;---等值连接查询
                      ---可以直接在select子句中使用字段直接获取数据,但是效率低,建议字段前加上表名
                      ---注意:如果是公共字段必须声明表名
                       select * from emp e,dept d where d.deptno=e.deptno;
      ---不等值链接
             ----查询员工的姓名,工作,工资,工资等级
             select * from emp e,salgrade s where e.sal>=s.losal and e.sal<= s.hisal; 
      ---自连接
             ----相当于自己和自己做笛卡尔积
             ----查询员工姓名,工作,薪资,以及上级领导姓名
            select e1.ename,e1.job,e1.sal,e2.ename from emp e1,emp e2 where e1.mgr=e2.empno;
      ---外链接
            ----左外链接
                   ---查询员工姓名,工作,薪资,部门名称以及没有部门的员工信息
                   select * from emp e,dept d where e.deptno=d.deptno(+); 
            ----右外链接
                   ---查询员工姓名,工作,薪资,部门名称以及没有员工的部门
                   select * from emp e,dept d where e.deptno(+)=d.deptno; 
----SQL99多表查询
----注意1:依然可以给表添加别名
----注意2;如果使用on或则usering关键字必须对结果进行筛选,必须使用inner join关键字组员于表与表的连接,其中inner可以省去
----注意3:外连接的outer关键字可以不写
----注意4:依然可以使用排序等关键字
             
     ----1.笛卡尔积:使用cross join关键字
           -----select 内容 from 表名 cross join
           -----查询员工及其部门
           select * from emp cross join dept;
     ----2.筛选
           -----自然连接:使用关键字natrual join
                  ----使用:select 内容 from 表名 natural join 表名
                  select* from emp natural join dept;
                  ---特点1:底层是笛卡尔积,按照同名同值字段自动进行等值筛选     
                  ---缺点1:如果想按照字段名不同,但是字段值不同筛选怎么办?
                  ----缺点2:如果只想按照部分字段结果筛选怎么办?    
                  ----解决1:使用using关键字
                          --作用1:指明使用指定的字段对联合查询的结果进行等值筛选
                          --注意:指明的字段必须是两边同名同值字段
                          --使用:select 内容 from 表名 inner join 表名 using(字段名)
                  select * from emp inner join dept using(deptno,ename);--底层相当于先做了一个笛卡尔积,再进行等值筛选
                  ------解决2:使用on关键字,进行自定义链接查询
                         ----注意:普通筛选使用where筛选不使用on  好处:便于阅读
                         ----使用:select 内容 from 表名 inner join 表名 on 连接条件 where 普通筛选条件
                         select * from emp inner join dept on emp.deptno=dept.deptno where job='SALESMAN';
          ------内连接
	           ---1.等值链接
		             ----先做表的笛卡尔积,然后筛选,筛选条件为等值筛选.
	                 ---查询员工的姓名,工作,薪资,部门名称
                        select * from emp inner join dept on dept.deptno=emp.deptno;---等值连接查询
                      ---可以直接在select子句中使用字段直接获取数据,但是效率低,建议字段前加上表名
                      ---注意:如果是公共字段必须声明表名
                        select * from emp e inner join dept d on d.deptno=e.deptno;
		       ---2.不等值链接
		             ----查询员工的姓名,工作,工资,工资等级
		                select * from emp e,salgrade s where e.sal>=s.losal and e.sal<= s.hisal; 
               ---3.自连接
                   	-----查询员工姓名,工作,薪资,以及上级领导姓名
                        select e1.*,e2.ename from emp e1 inner join emp e2 on e1.mgr=e2.empno;
           ------外连接
                    ----左外连接:select 内容 from 表名 left outer join 表名 on 筛选条件
                        ---查询员工姓名,工作,薪资,部门名称以及没有部门的员工信息
                        select * from emp e left outer join dept d on d.deptno=e.deptno;
                    ----右外连接:select 内容 from 表名 right outer join 表名 on 筛选条件
                         ---查询员工姓名,工作,薪资,部门名称以及没有员工的部门
                         select * from emp e right outer join dept d on d.deptno=e.deptno;
                    ----全外连接:select 内容 from 表名 fill outer join 表名 on 筛选条件
                         select * from emp e full outer join dept d on d.deptno=e.deptno;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章