普通的 select…from 很明显不能满足我们的更细化的查询需求,它除了基本语法外,还可以拓展使用一些判断语法和过滤、分组语法。本文介绍一些 select 的进阶查询语法。其中包括等值连接、不等值连接、外连接(左外连接、右外连接)自连接、层次查询、子查询(相关子查询)等语法。本文所操作的均是 oracle 下 scott 用户下的表。大家可参考查阅。
条件判断中使用=判断
select e.empno, e.ename, e.sal, d.dname
from emp e, dept d
where e.deptno = d.deptno
order by dname asc
条件判断中不使用=判断
select e.ename, e.empno, e.sal, s.grade
from emp e, salgrade s
where e.sal between s.losal and s.hisal;
希望在最后结果中,对于 where 条件来说不成立的记录,左外连接就是在表达式右侧增加(+),相反,右外连接是在表达式左侧增加(+)。 左外连接:
select d.deptno, d.dname, count(e.ename)
from emp e, dept d
where d.deptno = e.deptno(+)
group by d.deptno, d.dname
右外连接:
select d.deptno, d.dname, count(e.ename)
from emp e, dept d
where e.deptno(+) = d.deptno
group by d.deptno, d.dname
将一张表通过别名的方式视为多张表来查询
select e.ename ‘的老板是’ b.ename
from emp e, emp b
where e.mgr = b.empno
用来解决处理比较大的数据时自连接导致笛卡尔集比较大的问题,应用场景比较多的就是树状结构的数据,比如城市地区列表等。
select level, empno, ename, mgr
from emp
connect by prior empno = mgr
start with mgr is null
order by 1;
子查询其实就是嵌套 select 语句查询,嵌套的 select 要用小括号括起来,子查询可以写在 select 后面,也可以写在 from 后面,也可以写在 where 后面,但是写在不同的位置都有不同的规则,在 oracle 中子查询是非常需要得到重视的,所以子查询有如下十条规则。 1、合理的书写风格,该换行的地方换行,该缩进的地方缩进 2、小括号 3、主查询和子查询可以是不同的表,只要子查询出来的结果主查询可用就行了 4、可以在主查询的 where、selcet、having、from 后面都可以放子查询 5、group by 后面不能放子查询 6、from后面放置的子查询(***),from后面放置的是一个集合(表,查询结果) 7、一般情况下先进行子查询(内查询),再进行主查询(外查询)但是相关子查询除外 8、一般情况下不在子查询中使用order by(排序没有太大意义)Top-N必须使用 order by 9、单行子查询只能使用单行操作符,多行子查询只能使用多行操作符 10、子查询中null值 单行子查询案例:
select * from emp where sal > (select sal from emp where ename = ‘SCOTT’);
多行子查询案例: 查询部门名称为SALES和ACCOUNTING的员工信息,其中 in 语法表示等于条件中的任意一个都成立
select * from emp
where deptno in
(
select deptno
from dept
where dname = ‘SALES’
or dname = ‘ACCOUNTING’
);
查询比30号部门任意一个员工公司高的员工,其中 any 语法表示和集合中的任意一个值比较符合条件就可以
select * from emp
where sal > any
(
select sal
from emp
where deptno = 30
);
查询比30号部门所有人工资都高的人,其中 all 语法表示和集合内的所有值比较符合条件才可以
select * from emp
where sal > all
(
select sal
from emp
where deptno = 30
)
相关子查询就是主查询将某个值作为参数传递给子查询,请参考后面练习题第二题。
在 web 应用中,经常会对数据库有分页的需求,Oracle 不像其他数据库,有非常简单的分页函数,只能通过其提供的一个伪列 rownum 来实现。看如下例子。
select * from
(
select rownum r, empno, ename, sal from emp
)
where r >= 5 and r <= 10
1、求员工中所有人工资排前3名的人员
select * from
(
select rownum, empno, ename, sal
from emp
order by sal desc
)
where rownum <= 3
2、查找员工表中薪水大于本部平均薪水的员工 方法1:
select empno, ename, sal, s.avgsal
from emp, (select deptno, avg(sal) avgsal
from emp
group by deptno) s
where s.deptno = emp.deptno
and emp.sal > s.avgsal
方法2,使用相关子查询
select empno, ename, sal,
(
select avg(sal)
from emp
where deptno=e.deptno
) avgsal
from emp e
where sal >
(
select avg(sal)
from emp
where deptno=e.deptno
)
查询每年入职员工人数
select count(*) Total,
sum(decode(to_char(hiredate, ‘yyyy’), ‘1980’, 1, 0)) as “1980”,
sum(decode(to_char(hiredate, ‘yyyy’), ‘1981’, 1, 0)) as “1981”,
sum(decode(to_char(hiredate, ‘yyyy’), ‘1982’, 1, 0)) as “1982”,
sum(decode(to_char(hiredate, ‘yyyy’), ‘1987’, 1, 0)) as “1987”
from emp