跟我一起学Oracle 11g【8】SQL 基础学习2[连接查询]

前言

前面的查询主要都是针对一个表而言的。但是,在我们项目现实中,有更多的是多个表联合起来查询。所以,若一个查询同时涉及2个以上的表,那么我们就叫它为连接查询。连接查询是数据库中最重要的查询,主要包括等值连接查询、自然连接查询、非等值连接查询,自身连接查询、外连接查询和复合条件查询。

一。连接查询

1.1等值与非等值查询

连接查询的where字句总用来连接2个表的条件称为连接条件或者连接谓词。格式如下:

[<表名>.] <列名> <比较运算符> [<表名>.] <列名>

其中比如运算符有:等于(=)、大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、不等于(用!=或者用<>都可以)等。

连接条件我们还可以使用我们在上面一张提到过的 between....and的形式:

[<表名>] <列名> between [表名] <列名> and[表名] <列名>

使用“=”叫等值连接,其他则称为非等值连接。

【例子1】查询每个学生及其选修课的情况

我们在select字句中加上了表名,这样是为了防止混淆。如果属性名在参加连接的各表中是唯一的,则可以省略表名前缀。因为在我们的student表和course表均有sno,所以就不能省略咯。

我们也可以使用as 为表指定别名。

当然,我们这里使用表的别名的效果不太明显,如果在多张表连接起来的时候,使用通俗易懂的表名对我们有很大的帮助。

如果在等值连接中,把目标列中重复的属性列去掉则为自然连接。

【例子2】用自然连接重现例子1

因为sno在2个表都有,所以需要指定表名前缀,而其余的由于不冲突,所以可以不用。

1.2自连接

连接不仅可以再2个表中进行连接,而且还可以一个表自己和自己进行连接。

自连接主要是用来显示上下级关系或者层次关系的,

【例子3】查询每一门课的简介先修课(也就是先修课的先修课)

因为早course表中,只有每门课的直接先修课,而没有先修课的先修课。要得到这个信息,就必须先对一门课找到其先修课,在按照此先修课的课程号,查找它的先修课。

我们定义了2个表,first表和second表,

这里可能有点绕,需要好好琢磨琢磨这里。

自连接我在一个oracl数据自带的一个例子,可能比较更好的理解。在Oracle中有一个表叫emp(conn scott/tirger),emp表里有一个列叫mgr,他是每个员工管理者的员工号,如果员工没有管理者则mgr为空。(比如在公司里,员工都属于某个经理,经理属于老板,而老板上面没有人了就为空。)

OK,那我们现在需要找出谁是谁的manger,什么意思呢?我现在要找比如blake和clark的老板是king。。

select m.ename || ' is ' || n.ename || ' Manger'
from emp m,emp n
where n.mgr=m.empno;

结果如下:

这里找出了谁是谁的manger,用的就是自连接。

1.3外连接

OK,我们现在在学生表Student中加入一条数据:

insert into student values(005,'XiaoZhang','Male',18,'IS');

然后,我们在【例子2】去查:

我们没有找出XiaoZhang这个人。因为XiaoZhang这个人没有选课,所以它的数据就被抛弃了。但是,我现在想要全部学生的信息,不管他有没有选课呢?那怎么办呢?这个时候,我们就需要使用外连接了。

外连接,分为左外连接、右外连接以及全连接

左外连接:不仅会返回连接表中满足连接条件的所有语句,而且还会返回不满足连接条件的连接符左边表的其他行。(比如例子4)

右外连接:不仅会返回连接表中满足连接条件的所有语句,而且还会返回不满足连接条件的连接符右1边表的其他行

全连接:列出所有表的值。

【例子4】重现【例子1】查询每个学生及其选修课的情况

因为用的是左外连接,所以把左边表student的值全部显示出来,而不用管它有没有选课。

右外连接也是一样,语句如下:

 select student.sno,sname,ssex,sage,sdept,cno,grade 
from student righ outer join sc on(student.sno=sc.sno);

全连接语法:

select student.sno,sname,ssex,sage,sdept,cno,grade 

from student inner join sc on(student.sno=sc.sno);

另外一种写法:

在oracle中,对左外连接和右外连接还有另外一种写法:

左外连接是:左条件 = 右条件(+)

右外连接是:左条件(+) = 右条件

比如,我们现在的例子,我们只需要这样也可以得到一样的结果:

select student.sno,sname,ssex,sage,sdept,cno,grade 
from student,sc
where student.sno=sc.sno(+);

结构也是一样的哦!。

Oracle 建议你用from语句后加Outer Join语法,而不是Oracle的Join操作符(+).而且(+)是要受下面的规则限制的,但Outer Join语法则不受。

  • 你不可以 在查询块中使用(+) 当它同时包含 join的from语句中
  • (+)只是在where语句中,并且只能对应一个表或视图的一行字段
  • 如果A和B做联接时有多个条件,那么(+)必须完善所有的匹配条件,
    如果没有 ,oracle不会警告你~只是结果自然不同的
  • 不 可以在作出一个表外查询 另张表内查询的(+)联接操作
  • 不可以用(+)外联接到自己 当然Self Join是可以的
  • 含 (+)的Where后的注意
    OR不可用
    IN不可用
    子查询不可用

我们这里也在举一个oracle数据库自带的例子。有2个表emp表(员工表)和dept表(部门表) 每一个员工属于不同的部门中。

左外连接:

select d.dname,e.ename
from emp e left outer join dept d on(e.deptno=d.deptno);
当然也可以这样写:
select d.dname,e.ename from emp e,dept d where e.deptno=d.deptno(+);

列出了所有左边列emp的员工名字(ename)。

右外连接:

1.4复合条件连接

所谓的复合条件查询,在where子句中可以有多个连接条件。

【例子5】查询选修课为2号课程并且成绩在90分以下的同学

select student.sno,sname,grade 
from student,sc where sc.sno=student.sno --连接谓词,需要先对表进行连接
and sc.Cno=2 and SC.Grade<=90; ---其他的限定条件

结果如下:

二。算数运算

当我们在执行查询的时候,我们也可以再数字列使用算术表达式(+,-,*,/)。其中,乘和除的优先级要高于加减。

【例6】为了应付上面的检查,现在需要把分数小于80分的人,加上20分。

select sname,grade+20 from student,sc 
where student.sno=sc.sno and grade<80;

结果如下:

三。集合查询

本来这部分应该放到下一章节里讲的,可是因为嵌套查询的内容比较多,所以就提前讲的,里面的一些嵌套内容大家先了解下。

select语句的查询结果是元组的集合,所有多个select语句的结构可以进行集合操作。

集合操作包括并操作Union、交操作Intersect、差操作except。需要特别注意的是,参加集合操作的各查询结果的列数必须相同;对应的数据类型也必须相同。

把这些和数学上的交集、并集以及差集就很好理解了。

3.1并操作Union

也就是or操作,把符合条件的列都列出来。

【例7】查询计算机系的学生以及年龄不大于20岁的学生

select *
from student
where sdept='CS'
Union
select *
from Student
where sage<20;

等价于:

 select * from student where sdept='CS' or sage<20;

结果如下:

使用Union将多个查询结果合并起来,系统会自动去除重复元组,如果要保留重复元组则要用Union All操作符。

3.2交操作Interact

【例7】查询计算机系的学生以及年龄不大于20岁的学生的交集

select *
from student
where sdept='CS'
Intersect
select *
from Student
where sage<20;

也就是等价于:

select * from student where sdept='CS' and sage<20;

结果如下:

【例8】查询既选修课程1又选修课程2的学生。

select sno from sc where cno=1 

intersect

select sno from sc where cno=2;

也就是:

select Sno
from sc
where cno=1 and Sno in(
             select Sno
             from sc
             where cno=2); ---这个表达式会在下面一章节中介绍。

3.3差集except

【例9】查询计算机系的学生以及年龄不大于20岁的学生的差集

select * from student where sdept='CS'
minus
select * from student where sage<20;

要记得的是不大于。等价于下面的SQL语句:

select *
from student 
where sdept='CS' and sage>20;

均可以得到下面的结果:

原文地址:https://www.cnblogs.com/damonlan/p/2635350.html