如何正确嵌套CTE

时间:2011-09-05 09:30:20

标签: sql-server

这个问题很少有人问过,但我仍然无法找到正确的答案或正确的方法:

...

;WITH CTE AS
(
  SELECT * FROM ...
)
SELECT *, [dbo].[udf_BetaInv](A, B, C, D) AS 'Loss'
FROM CTE
WHERE (Loss >= @MinRetention)

这不起作用,我无法创建存储过程,显然我不能在WHERE中使用Loss,因为在该范围内不存在。

我想用另一个CTE来包装这个,所以我可以把WHERE放在外面的那个但是似乎不起作用,试过这个:

;WITH CTE AS
(
  SELECT * FROM ...
)
SELECT *, [dbo].[udf_BetaInv(A, B, C, D) AS 'Loss'
FROM CTE,
RESULTS AS
(SELECT * FROM CTE)
  SELECT *
  FROM RESULTS
  WHERE (Loss >= @MinRetention)

但是它没有在SQL Server中编译,我得到一个错误,'''错误地放在上面的许多行但没有任何关系,如果我删除第二个CTE就可以了。

我只想避免代码重复,不想在select和in中调用我的[udf_BetaInv]两次。

3 个答案:

答案 0 :(得分:14)

你有一个你不应该拥有的中级SELECT。这应该有效:

;WITH CTE AS
(
  SELECT * FROM ...
),
RESULTS AS
(
  SELECT *, [dbo].[udf_BetaInv(A, B, C, D) AS 'Loss'
  FROM CTE
)
SELECT *
FROM RESULTS
WHERE (Loss >= @MinRetention)

答案 1 :(得分:7)

显然,第一个查询的问题是'Loss'只是一个列别名,不能在WHERE子句中使用。你是正确的,在CTE中使用它会避免重复表达。这是你如何做到的;

WITH CTE AS 
( 
    SELECT * FROM ... 
),
CteWithLoss AS ( 
    SELECT *, [dbo].[udf_BetaInv](A, B, C, D) AS 'Loss' 
    FROM CTE
)
SELECT *
FROM CteWithLoss 
WHERE (Loss >= @MinRetention);

旁注:看看你是否可以打破用;WITH开始CTE定义的习惯,而养成用分号结束所有SQL语句的习惯。它更具可读性和更好的实践。

答案 2 :(得分:0)

以下是嵌套with cte_data as ( Select * from [HumanResources].[Department] ),cte_data1 as ( Select * from cte_data ) select * from cte_data1 的示例。

std::function