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
答案 0 :(得分:32)
WITH
子句适用于subquery factoring,也称为公用表表达式或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
可以重构为:
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看到的性能优势越多,尽管优化器通常非常擅长弄清楚您正在做什么。
答案 1 :(得分:1)
可能没有。在实际优化查询之前,Oracle能够进行许多代数转换。很可能两个查询都将以相同的方式进行评估(它们将具有相同的执行计划)。
答案 2 :(得分:0)
此外,如果子查询包含分析函数(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