连接查询
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;