WITH子句和子查询的区别?
Posted
技术标签:
【中文标题】WITH子句和子查询的区别?【英文标题】:Difference between WITH clause and subquery? 【发布时间】: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
【问题讨论】:
这能回答你的问题吗? Difference between CTE and SubQuery? 【参考方案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
【讨论】:
以上是关于WITH子句和子查询的区别?的主要内容,如果未能解决你的问题,请参考以下文章