CTE 和子查询的区别? ?

从这个后 如何在以下过程中使用 ROW _ NUMBER?

答案有两个版本,一个使用 sub-query,另一个使用 CTE来解决同样的问题。

那么,与“子查询”相比,使用 CTE (Common Table Expression)的优势是什么呢? (因此,更多的 < em > 可读 是查询实际上在做的事情)

使用 CTE优于 sub-select的唯一好处是,我实际上可以使用 姓名sub-query。这两种 当一个 CTE 被用作一个简单的(非递归的) CTE?之间还有什么区别吗

103059 次浏览

在子查询与 很简单(非递归) CTE 版本中,它们可能非常相似。您必须使用分析器和实际的执行计划来发现任何差异,这将是特定于您的设置(所以我们不能告诉您完整的答案)。

将军中,CTE 可以递归使用,而子查询不能,这使得它们特别适合于树结构。

除非我遗漏了什么,否则您可以同样轻松地命名 CTE 和子查询。

我想主要的区别在于可读性(我发现 CTE 更具可读性,因为它在前面而不是在中间定义子查询)。

如果需要使用递归进行任何操作,那么在使用子查询时将遇到一些麻烦;)

公共表表达式的主要优点(当不用于 递归查询时)是封装,而不是必须在每个希望使用它的地方声明子查询,您可以定义它一次,但对它有多个引用。

但是,这意味着 没有只执行一次(根据 这个答案的前几次迭代,感谢所有注释)。如果引用多次,查询肯定有可能被多次执行; 查询优化器最终决定应该解释 CTE。

CTE对递归最有用:

WITH hier(cnt) AS (
SELECT  1
UNION ALL
SELECT  cnt + 1
FROM    hier
WHERE   cnt < @n
)
SELECT  cnt
FROM    hier

将返回 @n行(直到 101)。适用于日历,虚拟行集等。

它们也更易读(在我看来)。

除此之外,CTEsubqueries是相同的。

如果多次使用同一个子查询,则可以用一个 CTE 替换所有这些子查询,从而添加其他人的答案。这允许您更好地重用代码。

您还需要了解的一件事是,在老版本的 SQL Server 中(是的,许多人仍然需要支持 SQL Server 2000数据库) ,不允许使用 CTE,因此派生表是最佳解决方案。

一个没有提到的区别是,可以在联合的几个部分中引用单个 CTE

提示:

可以限制特定的 语句,方法是使用 MAXRECURSION提示以及 032,767 OPTION条款中

例如,你可以试试:

OPTION
(MAXRECURSION 150)


GO

没有人提到的一个重要事实是(至少在 postgres 中) ,CTE 是优化栅栏:

Https://blog.2ndquadrant.com/postgresql-ctes-are-optimization-fences/

也就是说,它们将被视为自己的原子查询,而不是被折叠到整个查询计划中。我缺乏专业知识来给出一个更好的解释,但是你应该检查你正在使用的 sql 版本的语义; 对于高级用户,如果你是控制查询规划器的专家级别,能够创建一个优化栅栏可以帮助性能; 然而,在99% 的情况下,你应该避免试图告诉查询规划器做什么,因为你认为会更快的可能比它认为会更快的更糟。:-)

  1. 对于 CTE,可以使用递归。

  2. 对于 CTE,您只需要编写一次,但是您可以在查询中的多个位置引用它。因此,它可以让您避免重复自己,还可能使查询更容易阅读和解释(即使在查询只引用一次的情况下)。

  3. CTE 似乎向查询优化器提供关于自身的元数据,因此如果在同一个查询中引用一个 CTE 多次(例如,如果它与自身连接) ,查询优化器可能会使用该元数据来改进整个查询执行计划(这似乎不会发生在子查询中)。

因此,总的来说,如果您想使用递归,或者您认为它会使您的代码更易于表示和解释,或者您不止一次地使用相同的子查询,那么使用 CTE。