忍受我,我是中级的新手。
我的问题是 - 我什么时候应该使用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语句中使用select而不是CTE - 我如何决定应该使用哪一个?
答案 0 :(得分:5)
对于简单的例子,它没有太大的区别。如果您需要使用Recursive功能来构建层次结构,那么您没有太多选择 - 您需要使用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)时停止并向左移动:
;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 ...
答案 1 :(得分:4)
我个人发现CTE版本更易读,特别是如果选择变大。
当您在主SELECT中多次使用派生表时,最好使用CTE,因为它告诉数据库您只想运行一次。如果优化器足够聪明,可以在from子句中检测两个相同的子选择并且只运行一次,我就不会感到惊讶:
with foo as (
select ..
from bar
)
select f1.*
from foo f1
join foo f2 on ...
VS
select f1.*
from (select ... from bar ) f1
join (select ... from bar) f2 on ...
我认为最重要的部分是保持一致(在你的写作和团队内部)。
答案 2 :(得分:3)
我注意到JOIN(特别是当与很多WHERE子句结合使用时)在涉及大数据集时可能会带来灾难性的表现。
CTE可以通过仅选择相关记录并加入这些子集来解决此问题。
将CTE视为一种预先选择,为最终的SELECT准备数据。
答案 3 :(得分:2)
我使用CTE的另一个原因并不是要替换派生表,而是要确保复杂的报告SQL包含正确的记录。因此,假设您正在执行某种类型的财务报告,并且您希望确保准确返回所需的记录。如果有10个连接,则很难判断数据是否正确。
因此,我使用CTE构建了一个复杂的查询。因此,例如我只想要符合某些标准的订单。第一个CTE是挑选出来的那个。我写它然后在CTE上运行一个选择。这告诉我我的基线订单数量,这样当我添加复杂性时,我可以立即看到数字的变化位置,并确定它是否应该更改或者我是否需要更改查询。如果我需要左连接或内部连接,或者我可能需要在相关表上的条件将其限制为一条记录,这可以让我快速了解。
通常当我这样做时,在进入最终选择之前我将链接CTES更简单。而这一点的另一个价值是,我发现在更改它们时,更容易维护这些复杂的报告查询。因此,假设我有一个链中的CTE,如:
然后,当我需要更改有关如何进行成本计算的内容时,更容易找到进行更改的位置并更容易检查最终结果。