§7.1 复杂查询语句的使用
使用SELECT语句和子查询(SUBQUERY)可以从一个或多个表、视图、实体视图中返回数据。
§7.1.1 相关子查询
可以将子查询(前面提到的as subquery)或In或exists当成where的一个条件的一部分,这样的查询称作子查询。
l where中可以包含一个select语句子查询;
l where中可以包含IN, EXISTS语句;
l 最多可嵌套16层;
l 层数过多会影响性能。
例:比如一个查询是否有专家既以研究所的名义申请基金项目又以大学系为单位申请项目(按规定只能以一个单位来申请):
SQL>select name,per_id,dept_name from univ_subjects
Where per_id in ( select
per_id from colle_subjects );
§7.1.2 外连接
招生中,如果所有学生的信息放在students表中,而部分有特长的学生在另一个表student_skill中同样有该学生信息。现在要全部列出所有学生,如果某个学生在表student_skill中有其特长信息,就显示特长内容,如果某个学生没有特长(在表student_skill中无其特长信息)就显示特长为空:
SQL>select
a.st_id, name, age,skill from students
a, student_skill b
Where
a.st_id=b.st_id(+)
Order by a.name;
Students结构为:
St_id varchar(20),
Name varchar2(10),
Age number(2),
Tot_score number(3),
... ...
Student_skill结构为:
St_id varchar(20),
Skill varchar2(20),
... ...
Students的记录,Student_skill的记录少。上面的“+”跟在记录少的表后面,它表示当没有与a.st_id匹配时就为b.st_id增加一空行。
+号在左边表示右关联,在右边表示左关联
St_id name tot_score skill
---------- ----------
------------- ------------------
1111 aaaa
600 足球
2222 bbbb
590 篮球
3333 cccc
620
4444 dddd
610 跳高
... ...
§7.1.3 自我连接
自我连接是在同一个表或视图内进行条件连接。下面语句返回的是每个雇员的名字及该雇员的经理的名字:
SELECT e1.ename||’ works for ’||e2.ename
"Employees and their Managers"
FROM emp e1, emp e2 WHERE e1.mgr = e2.empno;
Employees and their Managers
-------------------------------
BLAKE works for KING
CLARK works for KING
JONES works for KING
FORD works for JONES
SMITH works for FORD
ALLEN works for BLAKE
WARD works for BLAKE
MARTIN works for BLAKE
SCOTT works for JONES
TURNER works for BLAKE
ADAMS works for SCOTT
JAMES works for BLAKE
MILLER
works for CLARK
连接条件是e1.mgr =
e2.empno
§7.1.4 UNION,INTERSECT及MINUS
有时需要从多个表中组合具有一种相似类型的信息。Union可以完成将两个以上的表的相类似的查询结果合并在一起,并且相同的只取其一;如果union
all则表示返回所有行(不管是否重复)。Intersect返回在两个表中都有相同内容的信息。Minus则返回只在一个表中出现的信息。
1. 语法:
select ...
union[all]
select ...
select ...
intersect
select ...
select ...
minus
select ...
例:
sql>
select sum(balance) into lf_return from
(
select
sum(nvl(tran_val,0)*decode(db_cr_flag,'1',1,'0',-1,0) ) balance
from per_fix_det
where acc_no=as_acc_no
union all
select
sum(nvl(tran_val,0)*decode(db_cr_flag,'1',1,'0',-1,0) ) balance
from per_detail
where acc_no=as_acc_no
);
列出有特长的考生(在表students,student_skill同时出现):
sql>select name
from sutdents
intersect
select name from student_skill;
列出没有特长的考生(仅在表students出现):
sql>select name
from sutdents
minus
select name from student_skill;