Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to nest CTE properly

Tags:

sql-server

This question was asked few other times, but I still did not manage to sort out the right answer or proper way to do this:

...

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

This does not work and I cannot create the stored procedure, clearly I cannot use Loss in the WHERE because does not exist in that scope.

I would like to use another CTE to wrap this one so I can put the WHERE on the outer one but not does not seem to work, tried this:

;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)

But it does not compile in SQL Server, I get an error that a '(' is misplaces many rows above but has nothing to do, if I remove the second CTE it works fine.

I only want to avoid code duplication, not want to call my [udf_BetaInv] twice in the select and also in the where.

like image 601
Davide Piras Avatar asked Sep 05 '11 09:09

Davide Piras


People also ask

Can CTE be nested?

Specifying more than one WITH clause in a CTE isn't allowed. For example, if a CTE query definition contains a subquery, that subquery can't contain a nested WITH clause that defines another CTE.

How do you declare multiple CTE?

The principle is the same: separate CTEs by a comma and start the second CTE without the keyword WITH.

Is CTE better than subquery?

Advantages of Using CTE CTE can be more readable: Another advantage of CTE is CTE is more readable than Subqueries. Since CTE can be reusable, you can write less code using CTE than using a subquery. Also, people tend to follow logic and ideas easier in sequence than in a nested fashion.


1 Answers

You have an intermediate SELECT that you should not have. This should work:

;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)
like image 189
AakashM Avatar answered Oct 04 '22 22:10

AakashM