SQL:是否有任何理由使用子查询代替CTE?

时间:2018-10-27 08:24:54

标签: sql common-table-expression

我已经看到许多带有复杂嵌套子查询(以及子子查询和子子子查询等)的SQL示例。是否有任何理由编写这样的复杂查询而不是使用WITH和CTE,就像有人会使用编程语言中的变量来分解复杂的表达式一样?

特别是在性能上有优势吗?

3 个答案:

答案 0 :(得分:1)

除非您的查询计划告诉您子查询的性能优于CTE,否则我将使用CTE代替子查询。

  

特别是在性能上有优势吗?

子查询与简单(非递归)CTE版本相比,它们可能非常相似。您将必须使用探查器和实际执行计划来发现任何差异。

出于某些原因,我会使用CTE

  1. 通常,CTE可以递归使用,但是子查询不能使用它,这可以帮助您制作日历表或特别适合于树形结构。
  2. CTE将更易于维护和阅读(@Lukasz Szozda注释),因为您可以将复杂的查询分解为多个CTE并为其指定好名字,这在编写主查询时非常方便。

答案 1 :(得分:1)

您只能使用FROM子句中的子查询编写的任何查询以及常规联接都可以使用具有直接替换的CTE。

以下情况需要子查询

  • 相关子查询(通常不在FROM子句中)。
  • 横向联接(在LATERAL子句中支持APPLYFROM关键字的数据库中)。
  • 标量子查询。

有时,可以重写查询以避免这些结构。

FROM子句中的子查询(横向连接除外)可以使用CTE编写。

为什么使用子查询而不使用CTE?最重要的原因是CTE是SQL语言的后来版本。除了递归CTE外,实际上并不需要它们。当一个子查询被多次引用时,它们确实很方便,但有人可能会认为视图具有相同的目的。

如评论中所述,CTE和子查询的优化方式可能有所不同。这可能是性能的提高或降低,具体取决于查询和基础索引等。

答案 2 :(得分:0)

没有性能方面的考虑: CTE与SQL代码相比更具可读性,这意味着更易于维护和调试。 子查询(在FROM子句中)很好,只要很少,很小和很简单,因此转换为CTE实际上会使它更难阅读。 还有视图选项,大多数情况下可以防止sql代码重复。 出于性能考虑: CTE可能会变得越来越复杂。如果是这样,它们将变得过于冒险,以至于无法通过某些柚木和更改获得信任,并可能导致更积极的性能方法,例如将所有CTE转换为临时(#)。 子查询的行为与视图一样好,并且在大多数情况下都比CTE好。仍然变得太复杂可能会提示性能,并使性能优化变得困难。最终,可能有人需要对其进行调整,或者甚至将较重的部分提取出来以减轻主要选择。 只要视图由简单表和简单视图组成,具有优雅的SQL并在视图联接内尽可能链接可能的过滤器,则视图在提高复杂性方面会稍好一些。仍然加入两个复杂的视图将使您处于与复杂的CTE或子查询相同的情况。