Sql 我如何决定是否应该使用CTE?
请容忍我,我是新手 我的问题是-我应该什么时候使用CTE?我如何决定是否使用CTE 我应该在什么时候使用这个:Sql 我如何决定是否应该使用CTE?,sql,database,sql-server-2008,tsql,common-table-expression,Sql,Database,Sql Server 2008,Tsql,Common Table Expression,请容忍我,我是新手 我的问题是-我应该什么时候使用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
;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语句中使用select而不是CTE-我如何决定应该使用哪一个?我个人认为CTE版本更具可读性,尤其是当select变得更大时
当您在主选择中多次使用派生表时,最好使用CTE,因为它告诉数据库您只想运行一次。尽管如果优化器足够聪明,能够在from子句中检测到两个相同的子选择并只运行一次,我也不会感到惊讶:
with foo as (
select ..
from bar
)
select f1.*
from foo f1
join foo f2 on ...
vs
我认为最重要的部分是保持一致性(在你所写的内容和团队内部)。对于简单的例子,这没有多大区别。如果您需要使用这些功能来构建层次结构,那么您没有太多选择—您需要使用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
还应该注意的是,如果您作为子查询执行上述操作,并且表达式特别复杂,读者/维护人员有时可能需要时间来验证这两个子查询实际上是相同的,并且这两个子查询之间没有细微的差异
此外,如果缩进样式表示子查询应显示在其封闭查询的右侧,则构建在其他表达式上的表达式可能会导致所有代码向右移动,而对于CTE,则在构建每个子表达式(CTE)时会停止并移回左侧: vs: 我注意到,当涉及大型数据集时,连接(特别是与许多WHERE子句结合使用时)可能会产生灾难性的性能 CTE可以通过仅选择相关记录并连接这些子集来解决此问题
将CTE视为一种预选择,为最终选择准备数据。我使用CTE的另一个原因不是替换派生表,而是确保复杂的报表SQL包含正确的记录。因此,假设您正在做某种类型的财务报告,并且希望确保返回的记录完全符合您的要求。当您有10个联接时,很难判断数据是否正确 因此,我使用CTE构建了一个复杂的查询。例如,我只希望订单符合某些标准。第一个CTE就是挑选这些的那个。我编写它,然后在CTE上运行select。这会告诉我我的basline订单数量,这样当我增加复杂性时,我可以立即看到该数量在哪里更改,并确定它是否应该更改,或者是否需要更改查询。这让我可以相当快地知道是否需要左连接或内部连接,或者是否需要相关表上的条件将其限制为一条记录 通常,当我这样做时,我会在到达最终选择之前链接CTE,这要简单得多。这一点的进一步价值在于,我发现,当需要更改这些复杂的报告查询时,维护它们要容易得多。假设我有一个链中的CTE,如:
- 命令
- 费用汇总表
- 客户人口统计
然后,当我需要更改成本计算方法时,既可以更容易地找到进行更改的位置,也可以更容易地检查最终结果。Hmn。值得深思。谢谢你的精心设计,谢谢。我们将对此进行更深入的探讨,但这似乎是选择CTESQL服务器的一个非常有说服力的原因。通常情况下,即使是同一个CTE,也不会重复引用一次,更不用说在不同的派生表中查找公共子表达式了。@MartinSmith:非常遗憾,谢谢您提供的信息。我认为SQL Server优化器至少与Oracle或PostgreSQL中的优化器一样聪明。
;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
;WITH CTE1 AS (
SELECT
...
), CTE2 as (
SELECT
...
FROM CTE1
), CTE3 as (
SELECT
...
FROM CTE2
)
select * from CTE3
select *
from
(
select ...
from
(
select ...
from
(
select ...