代码之家  ›  专栏  ›  技术社区  ›  Stephen Turner

到CTE还是不到CTE

  •  26
  • Stephen Turner  · 技术社区  · 16 年前

    由于长期以来一直使用sql2000,我对公共表表达式的了解并不多。

    我给出的答案 here (#4025380) 和 here (#4018793) 因为他们没有使用CTE而违背了流程。

    我很感激对于递归,它们是beez-kneez,并且有一些查询可以通过它们的使用大大简化,但是在什么时候它们的使用只是轻率的呢?与子查询或联接相比,它们有很大的性能优势吗?它们真的简化了代码并使其更易于维护吗?

    简而言之,什么时候使用CTE而不是“较小的”语法是一个好的实践。

    4 回复  |  直到 13 年前
        1
  •  22
  •   KeithS    16 年前

    在以下情况下,通常应在普通子查询上使用CTE:

    • 您的查询需要递归(如您所指出的)
    • 子查询很大或很复杂
    • 包含查询很大或很复杂
    • 子查询是重复的(或者至少可以通过对一个公共子查询执行不同的简单操作来简化几个子查询)

    简言之,是的,它们确实使查询在使用得当时更具可读性。

        2
  •  18
  •   Community Mohan Dere    9 年前

    就我个人而言,一旦我习惯了使用它们,我认为它们会产生更干净、更可读的代码。例如,将你的答案与我的答案进行比较 #4018793 . 我们基本上做了同样的事情;我用了CTE,而你没有。

    无CTE的回答:

    SELECT
        course,
        section,
        grade,
        gradeCount
    FROM
        table
    INNER JOIN
        (SELECT
            grade,
            Max(gradeCount) as MaxGradeCount
        FROM
            table
        ) MaxGrades
        ON  table.grade = MaxGrades.grade
            AND table.gradeCount = MaxGrades.MaxGradeCount
    ORDER BY 
        table.grade
    

    我对CTE的回答是:

    ;with cteMaxGradeCount as (
        select 
            grade, 
            max(gradeCount) as MaxGradeCount
        from @Test
        group by grade
    )
    select 
        t.course, 
        t.SECTION, 
        t.grade, 
        t.gradeCount
    from cteMaxGradeCount c
    inner join @Test t
        on  c.grade = t.grade
            and c.MaxGradeCount = t.gradeCount
    order by t.grade
    
        3
  •  3
  •   OMG Ponies    16 年前

    它们是句法上的糖分,除了层次/递归查询。

    然而,并不是所有可以递归地完成的事情都应该是——通过递归CTE生成日期几乎没有比光标更好——数字表技巧缩放得更好。

        4
  •  2
  •   NG.    14 年前

    CTE在递归场景中生成更快的结果。CTE的结果反复用于获取最终结果集。因此,既然您已经在CTE中使用了WHERE子句或子查询,那么它肯定会显示性能的改进。
    参考文献: http://msdn.microsoft.com/en-us/library/ms190766(v=sql.105).aspx

    请注意,在许多情况下,临时表比CTE的性能更好,因此您也应该尝试使用临时表。
    参考文献: http://social.msdn.microsoft.com/Forums/en/transactsql/thread/d040d19d-016e-4a21-bf44-a0359fb3c7fb