2012-07-12 17 views
3

忍受着我,我是中级新手。如何决定是否应该使用CTE?

我的问题是 - 当我应该使用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 

在此:

select * 
from testing.second_table s 
     inner join 
     (
      select * 
      from testing.first_table 
     ) t 
     on s.key = t.key 

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

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

回答

5

对于简单的例子,它并没有太大的差别。如果您需要使用Recursive功能来构建层次结构,那么您没有太多选择 - 您需要使用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 

还应当指出的是,如果你做了以上的子查询,和表情特别复杂,有时可能需要时间读/维护者,以验证两个子查询实际上是相同的,并且有两个


有一些细微的差别不同时,如果你有一个表示子查询应该进一步出现的缩进样式比其封闭的查询权,那么建立在其他表达式都可能会导致所有的代码转移到右侧 - 而用热膨胀系数,你停下并返回到左建立各子表达式(CTE):

;WITH CTE1 AS (
    SELECT 
    ... 
), CTE2 as (
    SELECT 
    ... 
    FROM CTE1 
), CTE3 as (
    SELECT 
    ... 
    FROM CTE2 
) 
select * from CTE3 

VS:

select * 
from 
    (
     select ... 
     from 
      (
       select ... 
       from 
        (
          select ... 
+0

非常详细 - 谢谢你。将探索这一点,但这一切看起来像选择CTE – Codingo 2012-07-12 07:43:31

4

亲自找到CTE版本更具可读性,特别是如果选择变大。

当您使用派生表超过主一旦选择它可能是最好使用CTE,因为它告诉您要一次运行该数据库。虽然我不会感到惊讶,如果优化是足够聪明来检测在FROM子句中两个相同的子选择和只运行过一次:

with foo as (
    select .. 
    from bar 
) 
select f1.* 
from foo f1 
    join foo f2 on ... 

select f1.* 
from (select ... from bar) f1 
    join (select ... from bar) f2 on ... 

我觉得最重要的部分是要保持一致(跨越你写的和你的团队内部)。

+0

SQL Server不一般跑多次提到有一次甚至同一CTE [没有一些黑客(http://connect.microsoft.com/SQLServer/feedback/details/218968/)让共同表达子单独看在不同的派生表中很不幸。 – 2012-07-12 08:56:58

+0

@MartinSmith:谢谢你提供的信息。我认为SQL Server优化器至少会像Oracle或PostgreSQL那样聪明。 – 2012-07-12 09:22:37

2

我注意到联接(ESP。当与大量WHERE子句结合使用时)在涉及大型数据集时可能会造成灾难性的性能。

热膨胀系数可以通过只选择相关记录,并加入了这些子集解决此问题。

考虑一个CTE为一种的预选择为最终SELECT准备数据。我用的CTE

+0

Hmn非常令人信服的理由。值得多思考。这次真是万分感谢 – Codingo 2012-07-12 07:42:56

2

的另一个原因是不是要取代派生表,但要保证复杂的报告SQL包含正确的记录。所以假设你正在做某种类型的财务报告,并且你想确保你完全返回你想要的记录。当你有10个连接时,很难判断数据是否正确。

因此,我使用CTE构建了一个复杂的查询片段。例如,我只想要符合特定标准的订单。第一个CTE是挑选出来的那个。我写它,然后在CTE上运行一个选择。这告诉我我的订单数量,因此当我增加复杂性时,我可以直接看到数字更改的位置,并确定它是否应该更改,或者是否需要更改查询。如果我需要左连接或内连接,或者如果我可能需要相关表上的条件将其限制为一条记录,这可以让我很快知道。

通常当我这样做,我会已链接CTES之前,我的最终选择是要简单得多。更进一步的价值在于,我发现在需要更改这些查询时,维护这些复杂的报表查询要容易得多。因此,假设我有热膨胀系数在这样一个链条:

  • 订单
  • 成本汇总表
  • 客户人口统计

然后,当我需要改变我是如何做的成本计算财产以后,它是更容易找到更改的位置,更容易检查最终结果。

相关问题