【问题标题】:Difference between WITH clause and subquery?WITH子句和子查询的区别?
【发布时间】:2015-07-16 16:36:14
【问题描述】:

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

【问题讨论】:

标签: sql oracle subquery common-table-expression


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    WITH 子句用于subquery factoring,也称为公用表表达式或 CTE:

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

    在您的第二个示例中,您所称的 temp_table 是内联视图,而不是临时表。

    在许多情况下,选择使用哪一个取决于您喜欢的样式,而 CTE 可以使代码更具可读性,尤其是在具有多级子查询的情况下(当然意见会有所不同)。如果您只参考 CTE/inline 视图一次,您可能不会看到任何性能差异,并且优化器最终可能会采用相同的计划。

    当您需要在多个地方(例如在联合中)使用相同的子查询时,它们特别有用。您可以将内联视图拉出到 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
    

    可以重构为:

    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
    

    不再需要重复子查询。重复代码越复杂,从维护的角度来看,使用 CTE 就越有利。而且,子查询的开销越大,您可以从使用 CTE 中看到的性能优势就越大,尽管优化器通常很擅长弄清楚您在做什么。

    【讨论】:

      【解决方案3】:

      此外,如果子查询包含分析函数 (LEAD/LAG/etc),并且如果您想过滤分析函数的结果 - 使用 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
      

      【讨论】:

        猜你喜欢
        • 2012-05-27
        • 1970-01-01
        • 2013-06-20
        • 2023-03-24
        • 1970-01-01
        • 2021-12-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多