Sql server中的Cte是执行一次还是每次引用时执行?

pvj*_*jhs 5 sql-server common-table-expression

我有一个虚拟表

create table emp
(
  id int,
  name varchar,
  sal int
)

with cte1 as(
select * from emp where name like 'a%'
),  
cte2 as (
select * from cte1 where sal > 100
),
cte3 as (
select * from cte1 where id != 1223
)
select * from cte2
union all
select * from ct3
Run Code Online (Sandbox Code Playgroud)

以这种方式使用 cte 是否可以保证 cte1、cte2、cte3 仅运行一次?

虽然我可以检查查询计划,但是如果数据发生更改并且下次优化器决定以其他方式执行此操作,这是否可以保证行为不会改变?

use*_*983 4

“以这种方式使用 cte 是否可以保证 cte1、cte2、cte3 仅运行一次?” 不。您此处的查询不会“运行”cte1一次,而是会运行两次。这可以在查询的查询计划中看到,您可以看到emp出现了两次。

这是因为,在最终选择中SELECT,您同时参考了cte3cte2。这两者都引用cte1,后者又引用emp。结果,对cte3和 的调用cte2导致对对象的 2 次调用emp

从技术上讲,如果您愿意,您可以将上面的内容重写为下面的内容;这可能会帮助您了解为什么emp被引用两次:

SELECT *
FROM (SELECT *
      FROM (SELECT *
            FROM emp
            WHERE [name] LIKE 'a%') AS cte1
      WHERE sal > 100) AS cte2
UNION ALL
SELECT *
FROM (SELECT *
      FROM (SELECT *
            FROM emp
            WHERE [name] LIKE 'a%') AS cte1
      WHERE id != 1223) AS cte3;
Run Code Online (Sandbox Code Playgroud)