我如何决定是否应该使用CTE?

Mic*_*l A 4 sql t-sql database common-table-expression sql-server-2008

忍受我,我是中级的​​新手.

我的问题是 - 我什么时候应该使用CTE?我该如何决定是否应该使用CTE?

我什么时候应该用这个:

;with cteTesting as
(
    select  *
    from    testing.first_table
)
select  *
from    testing.second_table s
        inner join cteTesting t
            on s.key = t.key
Run Code Online (Sandbox Code Playgroud)

在此:

select  *
from    testing.second_table s
        inner join
        (
            select  *
            from    testing.first_table
        ) t
        on s.key = t.key
Run Code Online (Sandbox Code Playgroud)

为什么?这只是代码流,代码可读性 - 还是有更技术性的东西?在某些情况下,会产生更好的执行计划吗?

编辑:刚刚意识到我的示例代码示例很差.我试图强调,在很多情况下我可以在from语句中使用select而不是CTE - 我如何决定应该使用哪一个?

Dam*_*ver 5

对于简单的例子,它没有太大的区别.如果您需要使用递归功能来构建层次结构,那么您没有太多选择 - 您需要使用CTE.

另一种情况是它可能没有太大的性能差异,但是为了便于阅读,就是需要多次加入同一个子查询时.如果您正在使用子查询,则必须重复整个表达式,而对于CTE,您只需使用两次名称:

;With NamedExpression as (
    select t1.ID,t2.ID as ID2,SUM(t3.Value) as Val
    from
      Table1 t1
        left join
      Table2 t2 on t1.id = t2.t1id
         inner join
      Table3 t3 on t3.col = t1.id or t3.col2 = t2.id
    group by
      t1.ID,t2.ID
)
select
    *
from
    NamedExpression ne
        inner join
    NamedExpression ne2
        on
            ne.ID2 = ne2.ID
Run Code Online (Sandbox Code Playgroud)

还应该注意的是,如果你做上面的子查询,并且表达式特别复杂,读者/维护者有时需要时间来验证两个子查询实际上是相同的,并且它们之间没有一些细微的差别.二


此外,如果您有一个缩进样式,表明子查询应该显示在右边而不是它们的封闭查询,那么构建在其他表达式上的表达式可能会导致所有代码向右移动 - 而对于CTE,您可以停止并移动在构建每个子表达式(CTE)时返回左侧:

;WITH CTE1 AS (
    SELECT
    ...
), CTE2 as (
    SELECT
    ...
    FROM CTE1
), CTE3 as (
    SELECT
    ...
    FROM CTE2
)
select * from CTE3
Run Code Online (Sandbox Code Playgroud)

VS:

select *
from
   (
        select ...
        from
             (
                 select ...
                 from
                     (
                          select ...
Run Code Online (Sandbox Code Playgroud)