来自这篇文章如何在以下过程中使用ROW_NUMBER?
答案有两种版本,一种使用a sub-query
,另一种使用a CTE
来解决相同的问题。
现在,使用CTE (Common Table Expression)
“子查询”而不是“子查询”有什么好处(因此,查询的实际可读性更高)
使用的唯一的优点CTE
了sub-select
,是我可以实际命名的sub-query
。当将CTE用作简单(非递归)CTE时,这两者之间还有其他区别吗?
来自这篇文章如何在以下过程中使用ROW_NUMBER?
答案有两种版本,一种使用a sub-query
,另一种使用a CTE
来解决相同的问题。
现在,使用CTE (Common Table Expression)
“子查询”而不是“子查询”有什么好处(因此,查询的实际可读性更高)
使用的唯一的优点CTE
了sub-select
,是我可以实际命名的sub-query
。当将CTE用作简单(非递归)CTE时,这两者之间还有其他区别吗?
Answers:
在子查询与简单(非递归)CTE版本中,它们可能非常相似。您将必须使用探查器和实际的执行计划来发现任何差异,而这将特定于您的设置(因此我们无法完全告诉您答案)。
在一般 ; CTE可以递归使用;子查询不能。这使得它们特别适合于树形结构。
A CTE can be used recursively; a sub-query cannot
。一个例子会很棒。
Common Table Expression(当不将其用于递归查询时)的主要优点是封装,而不是必须在希望使用它的每个位置声明子查询,您只需定义一次即可,但是有多个引用对此。
但是,这并不能意味着它只执行一次(按照这个非常的答案以前的迭代,感谢所有那些评论)。如果多次引用,该查询肯定有可能多次执行。查询优化器最终决定如何解释CTE。
CTE
对于递归最有用:
WITH hier(cnt) AS (
SELECT 1
UNION ALL
SELECT cnt + 1
FROM hier
WHERE cnt < @n
)
SELECT cnt
FROM hier
将返回@n
行(最多101
)。对于日历,虚拟行集等有用。
它们也更具可读性(我认为)。
除此之外,CTE
的和subqueries
是相同的。
;WITH blabla AS ...)
WITH
)MERGE
和类似版本上强制执行它
除非我缺少任何内容,否则您可以轻松命名CTE和子查询。
我猜主要的区别在于可读性(我发现CTE更具可读性,因为它在前面而不是在中间定义了子查询)。
而且,如果您需要对递归进行任何操作,那么在使用子查询进行操作时会遇到麻烦;)
没有人提到的一个重要事实是(至少在postgres中)CTE是优化围栏:
https://blog.2ndquadrant.com/postgresql-ctes-are-optimization-fences/
也就是说,它们将被视为自己的原子查询,而不是合并到整个查询计划中。我缺乏专业知识来提供更好的解释,但是您应该检查所使用的sql版本的语义。对于高级用户,如果您是控制查询计划者的专家级别,那么能够创建优化围栏可以提高性能;但是,在99%的情况下,应该避免尝试告诉查询计划者该怎么做,因为您认为更快的速度可能会比其认为更快的速度更糟。:-)