with子句是sql-99标准的内容,在oracle9.2中被引入。with子句可以用来命名子查询。当子查询在多个地方被使用时,可以直接使用查询
with子句是sql-99标准的内容,,在oracle9.2中被引入。with子句可以用来命名子查询。当子查询在多个地方被使用时,可以直接使用查询名。该子句命名的子查询会被优化器当成内联视图或临时表对待。后一种情况可以提高查询效率。
使用scott模式,对于每名员工取得他所在部门的人数,使用内联视图可以实现如下:
select e.ename as employee_name,
dc.dept_count as emp_dept_count
from emp e,
(select deptno, count(*) as dept_count
from emp
group by deptno) dc
where e.deptno = dc.deptno;
使用with子句,可以实现如下:
with dept_count as (
select deptno, count(*) as dept_count
from emp
group by deptno)
select e.ename as employee_name,
dc.dept_count as emp_dept_count
from emp e,
dept_count dc
where e.deptno = dc.deptno;
需求稍微变得复杂,现在在取得每名员工所在部门人数的同时,还要取得该员工的经理及其经理所在部门的人数。使用内联视图实现如下:
select e.ename as employee_name,
dc1.dept_count as emp_dept_count,
m.ename as manager_name,
dc2.dept_count as mgr_dept_count
from emp e,
(select deptno, count(*) as dept_count
from emp
group by deptno) dc1,
emp m,
(select deptno, count(*) as dept_count
from emp
group by deptno) dc2
where e.deptno = dc1.deptno
and e.mgr = m.empno
and m.deptno = dc2.deptno;
使用with子句实现如下:
with dept_count as (
select deptno, count(*) as dept_count
from emp
group by deptno)
select e.ename as employee_name,
dc1.dept_count as emp_dept_count,
m.ename as manager_name,
dc2.dept_count as mgr_dept_count
from emp e,
dept_count dc1,
emp m,
dept_count dc2
where e.deptno = dc1.deptno
and e.mgr = m.empno
and m.deptno = dc2.deptno;
显然,使用with子句结构更简洁,使用内联视图时出现两次的子查询,在使用with子句时只出现一次。
在没有重复子查询出现的情况下,也可以使用with子句简化复杂查询。下面的例子列出了所有开支大于平均开支的部门。
with
dept_costs as (
select dname, sum(sal) dept_total
from emp e, dept d
where e.deptno = d.deptno
group by dname),
avg_cost as (
select sum(dept_total)/count(*) avg
from dept_costs)
select *
from dept_costs
where dept_total > (select avg from avg_cost)
order by dname;
上面的查询,主体部分很简单,复杂的逻辑隐藏在了with子句中。
综上所述,该子句主要用来简化查询,增强语句可读性,提高查询效率。