简单的CTE如何工作?

时间:2017-02-17 10:01:07

标签: sql oracle common-table-expression

说,我有一个简短的查询。

[mAryValue removeObjectsAtIndexes:indicesToDelete];

我是否正确地假设查询首先通过with test_cte as( select * from table1 where conditions1 ) select * from table2 inner join test_cte on conditions2 where conditions3 来过滤基于test_cte的行,将数据存储在某处,然后再次遍历来自conditions1的剩余行加入table2时?那么它存储数据呢?内存?或者这相当于

test_cte

但更容易阅读大查询?

2 个答案:

答案 0 :(得分:2)

您的CTE只是派生表的语法变体(Oracle称之为内联视图):

select *
from table2
inner join
 (
   select *
   from table1
   where conditions1
 ) AS test_cte
on conditions2
where conditions3

一个体面的optmizer并不总是首先创建CTE / DT的结果(只有它过于复杂),所以在你的情况下,计划应该类似于你的第二个查询。只需比较两个查询的计划。

正如您所注意到的,CTE / DT主要用于通过将更复杂的查询分成更小的逻辑组来简化更复杂查询的编写,或者因为您需要在单个级别编写的内容,例如聚合顶部一个窗口聚合。

答案 1 :(得分:2)

  

"它在哪里存储数据?内存? "

这取决于。优化器将评估子查询的成本;如果成本足够高(可能是由于复杂性或大小),那么Oracle会将其实现为全局临时表并将其写入磁盘。因此,只有使用CTE才能获得明确的收益。

一个好处是我们可以在主查询中多次重复使用CTE结果。所以扩展你的例子:

with test_cte as(
    select *
    from table1
    where conditions1
)
select *
from table2
inner join test_cte
    on conditions2
where table1.whatever not in ( select whatever
                               from test_cte
                               where conditions3)

您在这里查询table1一次,但两次使用其记录。

CTE的另一个优点是我们可以链接它们:

with test_cte as(
    select *
    from table1
    where conditions1
)
, next_cte as (
   select t1.*
           , t23.*
   from test_cte t1
        join table23 t23
        on t1.id = t23.id)
select * 
from next_cte

这可以将复杂查询分解为更易于理解的块。但是,在开始这条路线之前,确保我们比优化器更聪明是非常重要的!

WITH子句的另一个用途是编写递归查询。从11gR2开始,这个结构允许我们在不使用Oracle的分层查询语法的情况下导航父子关系。 Find out more

with cte (id, parent_id, lvl) as
     ( select id, p_id, 0 as lvl
       from t23
       where p_id is null
       union all
       select t23.id, t23.p_id, cte.lvl + 1
       from cte
            join t23 
            on cte.id = t23.p_id)
select *
from cte
order by lvl, id
/