最近看到业内大佬的一篇文章,不由得产生共鸣,决定也写一篇实战研究文章,本次主要针对 with语句进行一定的剖析。
引用:
with子句或子查询分解子句是SQL-99标准的一部分,在Oracle 9.2中被添加到Oracle SQL语法中。with子句可以作为内联视图处理,也可以作为临时表解析。后者的优点是,对子查询的重复引用可能更有效,因为可以轻松地从临时表检索数据,而不是由每个引用请求数据。
实际生产环境当然也不能乱用,我们需要结合执行计划,10046 autotrace等工具,评估with语句的执行效率。
那么,在Oracle PL/SQL中,WITH子句是一个子查询分解子句,用于创建命名的子查询块。这个块充当SQL语句的虚拟表或内联视图。它最初是在Oracle 9.2中引入的。它减少了查询中一个表别名的多个引用的开销。with子句子查询块的作用域是与之关联的SELECT查询。
总结一下,就是一句话:WITH query_name子句允许将名称分配给子查询块。然后,通过指定查询名称,可以在查询中的多个位置引用子查询块。Oracle通过将查询名作为内联视图或临时表来优化查询 .
语法规则:
单个别名
WITH <alias_name> AS (subquery_sql_statement)
SELECT <column_name_list> FROM <alias>;
多个别名
WITH <alias_one> AS
(subquery_sql_statement),
<alias_two> AS
(sql_statement_from_alias_one)
SELECT <column_name_list>
FROM <alias_one>, <alias_two>
WHERE <join_condition>;
下面开始实战环节:
初始化案例:我们有一个业务场景需要大量的union all来完成测试数据:
select e.empno, e.ename, e.mgr, e.sal, d.deptno, d.dname
from (select 1 as empno, 5 as mgr, '老陈' as ENAME, 1000 as sal, 10 as deptno from dual
union all
select 2, 5, '千寻' ,2000, 10 from dual
union all
select 3, 6, '老李' ,3000, 20 from dual
union all
select 4, 6, '老王' ,2500, 20 from dual
union all
select 5, 7, '戴总' ,5000, 30 from dual
union all
select 6, 7, '郭姐' ,10000, 30 from dual) E
join (select 10 as DEPTNO, 'CONSULTANT' AS DNAME FROM DUAL
UNION ALL
SELECT 20, 'SALES' FROM DUAL
UNION ALL
SELECT 30, 'MANAGEMENT' FROM DUAL) D
ON (E.DEPTNO = D.DEPTNO)

当我们想要查询每个员工的经理名字时,将再次生成新的union all 关联结果,让正常的查询变得更加冗长

其实这里的逻辑本身是非常简单的,无非就是以别名e作为主表,和另一个拼接的别名m做一次左外关联,行源生成器打印的结果
可以看到千寻和老陈经理是戴总,老王和老李的经理是郭姐,下面看with语句的实现是如何操作的:
为了方便测试我们把临时结果集生成物理表
create table MYEMPS AS
select 1 as empno, 5 as mgr, '老陈' as ENAME, 1000 as sal, 10 as deptno from dual
union all select 2, 5, '千寻' ,2000, 10 from dual
union all select 3, 6, '老李' ,3000, 20 from dual
union all select 4, 6, '老王' ,2500, 20 from dual
union all select 5, 7, '戴总' ,5000, 30 from dual
union all select 6, 7, '郭姐' ,10000, 30 from dual;
create table mydepts as
select 10 as DEPTNO, 'CONSULTANT' AS DNAME FROM DUAL
UNION ALL SELECT 20, 'SALES' FROM DUAL
UNION ALL SELECT 30, 'MANAGEMENT' FROM DUAL

我们可以重复引用别名e员工表,即使是测试数据发生改变,我们也只需要针对指定子查询内部数据结构做响应调整
到目前为止,使用with语句有两个好处
1:重复的查询内容可以只调用一次,
2:增加了代码的阅读性




