CTE和子查询之间的区别?

从这篇文章如何在以下过程中使用ROW_NUMBER?

有两个版本的答案,其中一个使用SubQuery,另一个使用CTE来解决相同的问题。

那么,在子查询上使用CTE(公用expression式)有什么好处(因此,查询实际上在做什么更具可读性

使用CTE优于子select的唯一好处是我可以实际命名子查询。 当CTE被用作简单(非recursion)CTE时 ,这两者之间是否还有其他区别

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

一般来说 CTE可以recursion地使用; 一个子查询不能。 这使得它们特别适合于树结构。

公用表expression式 (当不用于recursion查询时 )的主要优点是封装,而不是必须在每个你想使用的地方声明子查询,你可以定义一次,但有多个引用到它。

但是,这并不意味着它只执行一次(按照此答案的前几次迭代 ,感谢所有那些已经评论过的)。 如果多次引用,查询肯定有可能被执行多次; 查询优化器最终决定如何解释CTE。

CTE对recursion最有用:

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

将返回@n行(最多101 )。 用于日历,虚拟行集等

他们也更可读(在我看来)。

除此之外, CTEsubqueries是相同的。

没有提到的一个区别是单个CTE可以在工会的几个部分中被引用

除非我错过了一些东西,否则你可以简单地命名CTE和子查询。

我猜主要区别是可读性(我发现CTE更易读,因为它定义了你的子查询而不是中间的)。

如果你需要用recursion来做任何事情,那么用子查询就会遇到一些麻烦;)

添加到其他人的答案,如果你有一个相同的子查询多次使用,你可以用一个CTEreplace所有这些子查询。 这使您可以更好地重用您的代码。

有一点你需要了解的是,在老版本的SQL Server(是的,许多人仍然需要支持SQL Server 2000数据库),CTE是不允许的,那么派生表是你最好的解决scheme。

build议:( MAXRECURSION n)

您可以通过使用MAXRECURSION提示和OPTION子句MAXRECURSION032,767之间的值来限制特定语句允许的recursion级别的数量

例如,你可以尝试:

 OPTION (MAXRECURSION 150) GO 

没有人提到的一个重要事实是(至less在postgres中),CTE是最优化的屏障:

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

也就是说,他们将被视为他们自己的primefaces查询,而不是折叠到整个查询计划中。 我缺乏提供更好解释的专业知识,但是您应该检查您正在使用的SQL版本的语义; 对于高级用户,如果您是控制查询规划师的专家级别,则可以创build优化围栏来帮助提高性能; 在99%的情况下,你应该避免试图告诉查询计划者该做什么,因为你认为更快的速度可能比它认为的更快。 🙂