在动态 sql 中执行 cte 表达式
Executing cte expression in a dynamic sql
我有以下 cte 表达式,我试图在动态 运行 中 sql 但我在其中收到无效标识符错误:
DECLARE @t TABLE ( ID INT, V float, D DATE )
INSERT INTO @t
VALUES ( 1, 1.2, '2014-01-01' ),
( 1, 1.33, '2014-01-02' ),
( 1, 1.33, '2014-01-03' ),
( 1, 7, '2014-01-04' ),
( 2, 5, '2014-01-04' ),
( 2, 8, '2014-01-10' ),
( 2, 11, '2014-01-05' );
DECLARE @DealClauseString nvarchar(max)
SET @DealClauseString =';WITH filter
AS ( SELECT ID ,
D ,
V ,
ROW_NUMBER() OVER ( PARTITION BY ID ORDER BY D DESC ) AS RN
FROM @t where id =1
),
cte
AS ( SELECT ID ,
D ,
V ,
MIN(D) OVER ( PARTITION BY ID ORDER BY D ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS Min ,
MAX(D) OVER ( PARTITION BY ID ORDER BY D ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS Max
FROM filter
WHERE RN <= 2
)
SELECT c1.ID ,
c2.V - c1.V AS V
FROM cte c1
JOIN cte c2 ON c1.ID = c2.ID AND c1.D < c2.D
WHERE ( c1.D = c1.MIN OR c1.D = c1.MAX )
AND ( c2.D = c2.MIN OR c2.D = c2.MAX ) '
exec @DealClauseString
有什么建议吗?
我还打算 运行 在 while 循环中使用这个 cte 表达式。 运行循环中的 cte 表达式是否存在任何性能问题?
首先,你不能 use a table variable with dynamic sql,所以你应该使用 #temp
table,尽管这可能只与你的示例代码相关。
其次,如果您使用动态sql,您要么需要将变量@DealClauseString
放在括号中,要么使用sp_executesql
,否则SQL Server assumes that you're calling a stored procedure.
CREATE TABLE #t ( ID INT, V FLOAT, D DATE )
INSERT INTO #t
VALUES ( 1, 1.2, '2014-01-01' ),
( 1, 1.33, '2014-01-02' ),
( 1, 1.33, '2014-01-03' ),
( 1, 7, '2014-01-04' ),
( 2, 5, '2014-01-04' ),
( 2, 8, '2014-01-10' ),
( 2, 11, '2014-01-05' );
DECLARE @DealClauseString NVARCHAR(MAX)
SET @DealClauseString = ';WITH filter
AS ( SELECT ID ,
D ,
V ,
ROW_NUMBER() OVER ( PARTITION BY ID ORDER BY D DESC ) AS RN
FROM #t where id =1
),
cte
AS ( SELECT ID ,
D ,
V ,
MIN(D) OVER ( PARTITION BY ID ORDER BY D ROWS
BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING ) AS Min ,
MAX(D) OVER ( PARTITION BY ID ORDER BY D ROWS
BETWEEN UNBOUNDED PRECEDING AND
UNBOUNDED FOLLOWING ) AS Max
FROM filter
WHERE RN <= 2
)
SELECT c1.ID ,
c2.V - c1.V AS V
FROM cte c1
JOIN cte c2 ON c1.ID = c2.ID AND c1.D < c2.D
WHERE ( c1.D = c1.MIN OR c1.D = c1.MAX )
AND ( c2.D = c2.MIN OR c2.D = c2.MAX ) '
EXEC (@DealClauseString)
结果:
ID V
1 5.67
我有以下 cte 表达式,我试图在动态 运行 中 sql 但我在其中收到无效标识符错误:
DECLARE @t TABLE ( ID INT, V float, D DATE )
INSERT INTO @t
VALUES ( 1, 1.2, '2014-01-01' ),
( 1, 1.33, '2014-01-02' ),
( 1, 1.33, '2014-01-03' ),
( 1, 7, '2014-01-04' ),
( 2, 5, '2014-01-04' ),
( 2, 8, '2014-01-10' ),
( 2, 11, '2014-01-05' );
DECLARE @DealClauseString nvarchar(max)
SET @DealClauseString =';WITH filter
AS ( SELECT ID ,
D ,
V ,
ROW_NUMBER() OVER ( PARTITION BY ID ORDER BY D DESC ) AS RN
FROM @t where id =1
),
cte
AS ( SELECT ID ,
D ,
V ,
MIN(D) OVER ( PARTITION BY ID ORDER BY D ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS Min ,
MAX(D) OVER ( PARTITION BY ID ORDER BY D ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS Max
FROM filter
WHERE RN <= 2
)
SELECT c1.ID ,
c2.V - c1.V AS V
FROM cte c1
JOIN cte c2 ON c1.ID = c2.ID AND c1.D < c2.D
WHERE ( c1.D = c1.MIN OR c1.D = c1.MAX )
AND ( c2.D = c2.MIN OR c2.D = c2.MAX ) '
exec @DealClauseString
有什么建议吗?
我还打算 运行 在 while 循环中使用这个 cte 表达式。 运行循环中的 cte 表达式是否存在任何性能问题?
首先,你不能 use a table variable with dynamic sql,所以你应该使用 #temp
table,尽管这可能只与你的示例代码相关。
其次,如果您使用动态sql,您要么需要将变量@DealClauseString
放在括号中,要么使用sp_executesql
,否则SQL Server assumes that you're calling a stored procedure.
CREATE TABLE #t ( ID INT, V FLOAT, D DATE )
INSERT INTO #t
VALUES ( 1, 1.2, '2014-01-01' ),
( 1, 1.33, '2014-01-02' ),
( 1, 1.33, '2014-01-03' ),
( 1, 7, '2014-01-04' ),
( 2, 5, '2014-01-04' ),
( 2, 8, '2014-01-10' ),
( 2, 11, '2014-01-05' );
DECLARE @DealClauseString NVARCHAR(MAX)
SET @DealClauseString = ';WITH filter
AS ( SELECT ID ,
D ,
V ,
ROW_NUMBER() OVER ( PARTITION BY ID ORDER BY D DESC ) AS RN
FROM #t where id =1
),
cte
AS ( SELECT ID ,
D ,
V ,
MIN(D) OVER ( PARTITION BY ID ORDER BY D ROWS
BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING ) AS Min ,
MAX(D) OVER ( PARTITION BY ID ORDER BY D ROWS
BETWEEN UNBOUNDED PRECEDING AND
UNBOUNDED FOLLOWING ) AS Max
FROM filter
WHERE RN <= 2
)
SELECT c1.ID ,
c2.V - c1.V AS V
FROM cte c1
JOIN cte c2 ON c1.ID = c2.ID AND c1.D < c2.D
WHERE ( c1.D = c1.MIN OR c1.D = c1.MAX )
AND ( c2.D = c2.MIN OR c2.D = c2.MAX ) '
EXEC (@DealClauseString)
结果:
ID V
1 5.67