Sql server 如何正确嵌套CTE

Sql server 如何正确嵌套CTE,sql-server,Sql Server,这个问题被问了几次,但我仍然没有找到正确的答案或正确的方法: 这不起作用,我不能创建存储过程,显然我不能在WHERE中使用Loss,因为该范围中不存在Loss 我想用另一个CTE来包装这一个,这样我可以把WHERE放在外面的一个上,但似乎不起作用,尝试了以下方法: ;WITH CTE AS ( SELECT * FROM ... ) SELECT *, [dbo].[udf_BetaInv(A, B, C, D) AS 'Loss' FROM CTE, RESULTS AS (SELECT

这个问题被问了几次,但我仍然没有找到正确的答案或正确的方法:

这不起作用,我不能创建存储过程,显然我不能在WHERE中使用Loss,因为该范围中不存在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,它就可以正常工作


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

显然,第一个查询的问题是'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);

另一方面:看看是否可以打破以
;以
开始CTE定义的习惯,转而养成以分号结束所有SQL语句的习惯。这更具可读性和更好的实践。

您有一个中间
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)

下面是嵌套
CTE
的示例

with cte_data as 
(
    Select * from [HumanResources].[Department]
),cte_data1 as
(
    Select * from cte_data
)

select * from cte_data1

你的意思是
[Loss]
(一个列名)不是
'Loss'
(一个字符串)?不确定这是否会导致错误,尽管谢谢,效果也很好,但我没有意识到我有太多的选择:这不是必需的,但用CTE名称显式命名列是一个很好的做法,即….结果([column names from CTE],Loss)……稍后您会感谢自己:P.我需要第一个CTE中的第二个CTE,查询取决于它。有什么方法可以做到这一点吗?另外一个是“打破以;开始CTE定义的习惯”这不是嵌套的,只是另一个CTE引用了以前的一个。这是嵌套的Dave。事实上,这几乎是嵌套CTE的定义。你想过递归CTE吗?这是一个全新的游戏,更有趣,但不是OP要求的。
with cte_data as 
(
    Select * from [HumanResources].[Department]
),cte_data1 as
(
    Select * from cte_data
)

select * from cte_data1