WITH子句和子查询之间的区别?

Har*_*Rao 24 sql oracle subquery common-table-expression

WITH子句和子查询之间有什么区别?

1. WITH table_name as ( ... )

2. select *
    from ( select curr from tableone t1
             left join tabletwo t2
               on (t1.empid = t2.empid)
         ) as temp_table
Run Code Online (Sandbox Code Playgroud)

Ale*_*ole 40

WITH子句用于子查询因子分解,也称为公共表表达式或CTE:

WITH query_name子句允许您为子查询块指定名称.然后,您可以通过指定query_name来引用查询中的多个位置的子查询块.Oracle数据库通过将查询名称视为内联视图或临时表来优化查询.

在第二个示例中,您调用的temp_table是内联视图,而不是临时表.

在许多情况下,使用哪种选择取决于您的首选风格,CTE可以使代码更具可读性,特别是对于多级子查询(当然,意见各不相同).如果您只看到CTE /内联视图,您可能看不到性能上的任何差异,并且优化器可能最终得到相同的计划.

当你需要在多个地方使用相同的子查询时,它们特别有用,例如在联合中.您可以将内联视图拉入CTE,这样代码就不会重复,并且如果它认为有益,它允许优化器实现它.

例如,这个人为的例子:

select curr from (
  select curr from tableone t1
  left join tabletwo t2 on (t1.empid = t2.empid)
) temp_table
where curr >= 0
union all
select -1 * curr from (
  select curr from tableone t1
  left join tabletwo t2 on (t1.empid = t2.empid)
) temp_table
where curr < 0
Run Code Online (Sandbox Code Playgroud)

可以重构为:

with temp_table as (
  select curr from tableone t1
  left join tabletwo t2 on (t1.empid = t2.empid)
)
select curr from temp_table
where curr >= 0
union all
select -1 * curr from temp_table
where curr < 0
Run Code Online (Sandbox Code Playgroud)

子查询不再需要重复.重复代码越复杂,从维护的角度来看,使用CTE越有利.而子查询的成本越高,使用CTE 就可以看到更多的性能优势,尽管优化器通常非常擅长弄清楚你正在做什么.


小智 6

此外,如果子查询包含分析函数(LEAD/LAG/等),并且如果您想过滤分析函数的结果 - 使用该方法SUBQUERY,您必须将结果插入临时表并执行过滤等临时表,而使用WITH子句时,您可以在同一查询中使用结果进行过滤/分组等

;WITH temp AS
(
    SELECT 
        ID
        , StatusID
        , DateChanged
        , LEAD(StatusID,1) OVER (PARTITION BY ID ORDER BY ID, DateChanged, StatusID) NextStatusID
    FROM 
        myTable 
    WHERE 
        ID in (57,58)
)
SELECT
    ID
    , StatusID
    , DateChanged
FROM
    temp
WHERE
    temp.NextStatusID IS NULL
Run Code Online (Sandbox Code Playgroud)


ibr*_*041 3

可能没有。Oracle 在实际优化查询之前能够进行许多代数转换。最有可能的是,两个查询将以相同的方式进行评估(它们将具有相同的执行计划)。