Sql 使用带窗口函数的递归CTE
我有一些数据,我想计算分组变量工作日内n的百分位数。我可以用一个while循环来做这个,但是我试着用一个CTE。当我尝试转换为CTE时,我得到: PERCENTILE_DISC函数的输入参数必须为常量 如何在递归CTE中使用窗口函数 将假数据集设为临时表 While循环解决方案 尝试使用递归CTE和错误消息Sql 使用带窗口函数的递归CTE,sql,sql-server,Sql,Sql Server,我有一些数据,我想计算分组变量工作日内n的百分位数。我可以用一个while循环来做这个,但是我试着用一个CTE。当我尝试转换为CTE时,我得到: PERCENTILE_DISC函数的输入参数必须为常量 如何在递归CTE中使用窗口函数 将假数据集设为临时表 While循环解决方案 尝试使用递归CTE和错误消息 你不能使用rCTE,或者最好是计数。正如状态和错误告诉您的,第一个参数必须是文本;列的值不是文本,因此不能使用 您可以使用动态语句来执行此操作,但这并不理想: DECLARE @SQL nv
你不能使用rCTE,或者最好是计数。正如状态和错误告诉您的,第一个参数必须是文本;列的值不是文本,因此不能使用 您可以使用动态语句来执行此操作,但这并不理想:
DECLARE @SQL nvarchar(MAX),
@CRLF nchar(2) = NCHAR(13) + NCHAR(10);
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT CONVERT(decimal(3,0),0) AS I
UNION ALL
SELECT CONVERT(decimal(3,0),ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) AS I
FROM N N1, N N2)
SELECT @SQL = STUFF((SELECT @CRLF + N'UNION' + @CRLF +
N'SELECT frm.[Weekday],' + @CRLF +
N' ' + FORMAT(T.I,'0') + N' AS Percentile,' + @CRLF +
N' PERCENTILE_DISC(' + FORMAT(T.I/100,'0.00') + N') WITHIN GROUP (ORDER BY frm.[n]) OVER(PARTITION BY frm.[Weekday]) AS n' + @CRLF +
N'FROM ##Temp AS frm'
FROM Tally T
ORDER BY T.I
FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,9,N'') + @CRLF +
N'ORDER BY Weekday, n, Percentile;'
--SELECT @SQL;
EXEC sys.sp_executesql @SQL;
DECLARE @PercentileLookup TABLE(
[Weekday] VARCHAR(250),
[Percentile] INT,
[n] INT
)
DECLARE @p INT;
SET @p=0;
WHILE @p < 101
BEGIN
INSERT INTO @PercentileLookup
SELECT DISTINCT
frm.[Weekday],
@p as Percentile,
PERCENTILE_DISC(CAST(@p AS FLOAT)/100) WITHIN GROUP (ORDER BY frm.[n]) OVER(PARTITION BY frm.[Weekday]) as n
FROM ##Temp as frm
SET @p = @p + 1;
END;
SELECT * FROM @PercentileLookup
ORDER BY Weekday, n, Percentile
WITH PercentileLookup(Weekday, Percentile, n) AS (
SELECT
frm.[Weekday],
0,
PERCENTILE_DISC(CAST(.0 AS FLOAT)/100) WITHIN GROUP (ORDER BY frm.[n]) OVER(PARTITION BY frm.[Weekday]) as n
FROM ##Temp as frm
UNION ALL
SELECT
frm.[Weekday],
Percentile + 1,
PERCENTILE_DISC(CAST(Percentile AS FLOAT)/100) WITHIN GROUP (ORDER BY frm.[n]) OVER(PARTITION BY frm.[Weekday]) as n
FROM PercentileLookup as pl
INNER JOIN ##Temp as frm ON frm.[Weekday] = pl.[Weekday]
WHERE Percentile <= 100
)
SELECT DISTINCT * FROM PercentileLookup
--Msg 8726, Level 16, State 1, Line 70
--Input parameter of PERCENTILE_DISC function must be a constant.
--Completion time: 2020-03-11T13:26:16.4701034-04:00
DECLARE @SQL nvarchar(MAX),
@CRLF nchar(2) = NCHAR(13) + NCHAR(10);
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT CONVERT(decimal(3,0),0) AS I
UNION ALL
SELECT CONVERT(decimal(3,0),ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) AS I
FROM N N1, N N2)
SELECT @SQL = STUFF((SELECT @CRLF + N'UNION' + @CRLF +
N'SELECT frm.[Weekday],' + @CRLF +
N' ' + FORMAT(T.I,'0') + N' AS Percentile,' + @CRLF +
N' PERCENTILE_DISC(' + FORMAT(T.I/100,'0.00') + N') WITHIN GROUP (ORDER BY frm.[n]) OVER(PARTITION BY frm.[Weekday]) AS n' + @CRLF +
N'FROM ##Temp AS frm'
FROM Tally T
ORDER BY T.I
FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,9,N'') + @CRLF +
N'ORDER BY Weekday, n, Percentile;'
--SELECT @SQL;
EXEC sys.sp_executesql @SQL;