`

WITH Clause : Subquery Factoring

 
阅读更多

Subquery Factoring

 

The WITH clause, or subquery factoring clause, is part of the SQL-99 standard and was added into the Oracle SQL syntax in Oracle 9.2. The WITH clause may be processed as an inline view or resolved as a temporary table. The advantage of the latter is that repeated references to the subquery may be more efficient as the data is easily retrieved from the temporary table, rather than being requeried by each reference. You should assess the performance implications of the WITH clause on a case-by-case basis.

 

This article shows how the WITH clause can be used to reduce repetition and simplify complex SQL statements. I'm not suggesting the following queries are the best way to retrieve the required information. They merely demonstrate the use of the WITH clause.

 

Using the SCOTT schema, for each employee we want to know how many other people are in their department. Using an inline view we might do the following.

 

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;

 

Using a WITH clause this would look like the following.

 

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;

 

The difference seems rather insignificant here.

 

What if we also want to pull back each employees manager name and the number of people in the managers department? Using the inline view it now looks like this.

 

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;

 

Using the WITH clause this would look like the following.

 

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;

 

So we don't need to redefine the same subquery multiple times. Instead we just use the query name defined in the WITH clause, making the query much easier to read.

 

If the contents of the WITH clause is sufficiently complex, Oracle may decide to resolve the result of the subquery into a global temporary table. This can make multiple references to the subquery more efficient. The MATERIALIZE and INLINE optimizer hints can be used to influence the decision. The undocumented MATERIALIZE hint tells the optimizer to resolve the subquery as a global temporary table, while the INLINE hint tells it to process the query inline.

 

WITH dept_count AS (
  SELECT /*+ MATERIALIZE */ deptno, COUNT(*) AS dept_count
  FROM   emp
  GROUP BY deptno)
SELECT ...

WITH dept_count AS (
  SELECT /*+ INLINE */ deptno, COUNT(*) AS dept_count
  FROM   emp
  GROUP BY deptno)
SELECT ...

 

Even when there is no repetition of SQL, the WITH clause can simplify complex queries, like the following example that lists those departments with above average wages.

 

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;

 

In the previous example, the main body of the query is very simple, with the complexity hidden in the WITH clause.

 

MATERIALIZE Hint

 

The undocumented MATERIALIZE hint was mentioned above, but there seems to be a little confusion over how it is implemented. We can see what is happening under the covers using SQL trace.

 

Create a test table.

 

CONN test/test

CREATE TABLE t1 AS
SELECT level AS id
FROM   dual
CONNECT BY level <= 100;

 

Check the trace file location.

 

SELECT value
FROM   v$diag_info
WHERE  name = 'Default Trace File';

VALUE
--------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/cdb1/cdb1/trace/cdb1_ora_4278.trc

SQL>

 

Trace a statement using the MATERIALIZE hint.

 

EXEC DBMS_MONITOR.session_trace_enable;

WITH query1 AS (
  SELECT /*+ MATERIALIZE */ * FROM t1
)
SELECT * FROM query1;

EXEC DBMS_MONITOR.session_trace_disable;

 

The following abbreviated output shows some points of interest in the resulting trace file. Notice the "CREATE GLOBAL TEMPORARY T" and "TABLE ACCESS FULL SYS_TEMP_0FD9D662B_2E34FB" lines. It certainly seems to be using a global temporary table.

 

=====================
PARSING IN CURSOR #140100560521424 len=174 dep=1 uid=0 oct=1 lid=0 tim=733844612 hv=1878591410 ad='80b179f0' sqlid='40a2untrzk1xk'
CREATE GLOBAL TEMPORARY T
END OF STMT
...
=====================
...
=====================
PARSING IN CURSOR #140100560423976 len=77 dep=0 uid=109 oct=3 lid=109 tim=733865863 hv=3518560624 ad='a35bc6c0' sqlid='9fzhbw78vjybh'
WITH query1 AS (
  SELECT /*+ MATERIALIZE */ * FROM t1
)
SELECT * FROM query1
END OF STMT
...
STAT #140100560423976 id=1 cnt=100 pid=0 pos=1 obj=0 op='TEMP TABLE TRANSFORMATION  (cr=15 pr=1 pw=1 time=19589 us)'
STAT #140100560423976 id=2 cnt=0 pid=1 pos=1 obj=0 op='LOAD AS SELECT  (cr=3 pr=0 pw=1 time=16243 us)'
STAT #140100560423976 id=3 cnt=100 pid=2 pos=1 obj=91676 op='TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=1514 us cost=3 size=300 card=100)'
STAT #140100560423976 id=4 cnt=100 pid=1 pos=2 obj=0 op='VIEW  (cr=12 pr=1 pw=0 time=1257 us cost=2 size=1300 card=100)'
STAT #140100560423976 id=5 cnt=100 pid=4 pos=1 obj=4254950955 op='TABLE ACCESS FULL SYS_TEMP_0FD9D662B_2E34FB (cr=12 pr=1 pw=0 time=1203 us cost=2 size=300 card=100)'
...
=====================

 

Note. This is an undocumented feature. I've given you an example that uses a global temporary table, but perhaps there are other circumstances that don't.

 

参考至:http://www.oracle-base.com/articles/misc/with-clause.php

如有错误,欢迎指正

邮箱:czmcj@163.com

分享到:
评论

相关推荐

    clause:聊天机器人,自然语言理解,语义理解

    Clause 是 Chatopera 团队自主研发及使用其他商业友好的开源软件的方式实现的,Clause 为实现聊天机器人提供强大的大脑,包括客服、智能问答和自动流程服务。Clause 利用深度学习,自然语言处理和搜索引擎技术,让...

    jslicense-bsd-2-clause:jslicense 格式的两条款(“简化”)BSD 许可证

    **JavaScript BSD 2-Clause 许可证详解** 在软件开发领域,许可证是规范代码使用、分发和修改的重要法律文档。`jslicense-bsd-2-clause` 是一种基于 JavaScript 的,采用两条款(“简化”)BSD 许可证的开源许可...

    oracle advanced sql 高级SQL教程 ORACLE官方教材

    WITH Clause: Example 4-27 Summary 4-29 Practice 4 Overview 4-31 iv 5 Hierarchical Retrieval Objectives 5-2 Sample Data from the EMPLOYEES Table 5-3 Natural Tree Structure 5-4 Hierarchical Queries 5-5 ...

    The Clause: Hemingwayapp to Medium-crx插件

    语言:English 从Hemingwayapp发布到Medium HemingwayApp是一个网络应用程序,可让您的写作大胆而清晰。 ... 该条款允许您从HemingwayApp发布到Medium。 您可以:1.选择文章的发布状态(草稿,公开或不公开)2....

    sanity-clause:通用Lisp的数据序列化合同库

    来源: 文件: 你不能骗我。 没有安全条款! -奇科·马克思健全条款是一个数据验证/合同库。 您可以将其用于配置数据,验证api响应或数据存储区中的文档。 使用动态类型的语言,它可以帮助您定义明确定义的疑问和不...

    条款:Hemingwayapp到中等「The Clause: Hemingwayapp to Medium」-crx插件

    从Hemingwayapp发布到媒体 海明威应用程序是一个网络应用程序,使您的写作大胆和清晰。不得不从HemingwayApp复制文章,然后去... 条款允许您从HemingwayApp发布到媒体。 您可以 :  1.... 2.... 3.... 4....支持语言:English

    with:支持GORM

    with := with . New ( db ). Append ( "`apple_buyers` AS (SELECT `user_id` FROM `sales` WHERE product = ?)" , "apple" ). Append ( "`orange_buyers` AS (?)" , db . Model ( & Sale {}). Select ( "user_id...

    relational-interpreter-with-match:关系 Scheme 解释器,用 miniKanren 编写,带有 Scheme 模式匹配器

    (match ,expr ,clause ,clauses ...) clause ::= (,toppattern ,expr) toppattern ::= selfevalliteral | pattern | (quasiquote ,quasipattern) pattern ::= var | (? ,pred ,var) quasipattern ::= literal | (,...

    Clause_37_Auto-Negotiation.pdf

    《Clause 37 自协商原理详解》 在现代网络通信技术中,自协商(Auto-Negotiation)是一项关键功能,特别是在千兆以太网(Gigabit Ethernet, GE)环境中。Clause 37 自协商机制是IEEE 802.3标准的一部分,它允许网络...

    SQL_ the Basics.pdf

    - subqueries in the "from" clause:在FROM子句中嵌套查询,用于复杂的数据检索。 - grouping, aggregation, and having clauses:通过GROUP BY进行分组,使用AGGREGATE函数(如SUM, AVG)进行聚合,HAVING子句则在...

    ISO9001:2015标准新版[1].pdf

    每个clause都对应着质量管理体系中的一个方面,从组织的背景到领导作用、策划、支持、运行、绩效评价和持续改进等。 理解 ISO 9001:2015 标准新版的要求 ISO 9001:2015 标准新版对组织的要求包括: * 确认组织...

    mysql8 公用表表达式CTE的使用方法实例分析

    本文实例讲述了mysql8 公用表表达式CTE的使用方法。...with_clause: WITH [RECURSIVE] cte_name [(col_name [, col_name] ...)] AS (subquery) [, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...

    Oracle行转列之pivot

    3. pivot_in_clause:定义了pivot_for_clause子句中列的过滤器,用于指定哪些列值将被用作结果集中的列标题。 一个简单的PIVOT操作示例中,首先可以查看基础数据,例如: ```sql SELECT job, deptno, SUM(sal) AS ...

    初中英语复习资料大全.doc

    17. be/feel confident with sth/that clause:对...有信心,表达自信状态。 18. be + doing:可以表示现在进行时或将来时。 19. be able to (+ v 原) = can (+ v 原):能够做某事。 20. be afraid of doing sth...

    oracle行列转换实例

    - Query-Partition-Clause: 根据指定的表达式将结果集逻辑地分成多个分区。 - Order-By-Clause: 对每个分区内的数据进行排序。 - Windowing-Clause: 定义窗口,可以是滑动窗口或固定窗口。 2. 行列转换的实例原理 ...

    2022版质量管理体系标准FDISISO9001汇编.pdf

    * Clause 4: Context of the organization * Clause 5: Leadership * Clause 6: Planning * Clause 7: Support * Clause 8: Operation * Clause 9: Performance evaluation * Clause 10: Improvement 这些条款的...

    Python库 | clause-1.1.2.tar.gz

    资源分类:Python库 所属语言:Python 资源全名:clause-1.1.2.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    WITH CHECK OPTION的用法

    如果操作试图修改不符合视图条件的数据,数据库将抛出ORA-01402错误,指出“view WITH CHECK OPTION where-clause violation”。 在给定的部分内容示例中: ```sql SQL&gt; insert into (select object_id, object_...

    openmp 3.0 summary

    **clause:** - `if (scalar-expression)`:根据标量表达式的值决定是否执行并行区域。 - `num_threads (integer-expression)`:指定并行区域中的线程数量。 - `default (shared|none)`:定义未被其他子句指定的变量...

    1000BASE-X IEEE 802.3-2008 Clause 36 - Physical Coding Sublayer (PCS)

    本文将深入探讨1000BASE-X和IEEE 802.3-2008 Clause 36中关于PCS的详细内容。 首先,我们要理解1000BASE-X的含义。"1000"代表1 Gbps的速率,"BASE"表示基带传输,"X"则意味着该标准采用了光纤或铜线介质的多种实现...

Global site tag (gtag.js) - Google Analytics