我有一个SQL表UDF,它从20天的移动平均值得到一个标准偏差......它的计算表是:Tickers([date] datetime,[close] numeric(7,2))< / p>
函数计算表GetStDev([date] datetime,stddev numeric(7,2)。
stddev列的最后一行总是NULL(由于STDEV计算?)...我需要用前一行的值([date] -1)替换最后一行中的NULL值。但是这样做,我是否已经计算了整个查询两次并从xxx中选择了TOP 1 stddev,即便如此我也不知道如何编写这么长的SQL语句......这是我的在线表UDF:< / p>
ALTER FUNCTION GetStdDev
(
@TKR VARCHAR(10)
)
RETURNS TABLE
AS
RETURN
(
SELECT x.[date], ISNULL(STDEV(y.[Close]),0) stdev
FROM Tickers x, Tickers y
WHERE x.[DATE] > (SELECT TOP 1 z.[DATE] FROM TICKERS z WHERE z.TICKER = @TKR ORDER BY z.DATE ASC)+20
AND (DATEDIFF(day, x.[date], GETDATE()) <= 730)
AND x.TICKER = @TKR AND y.TICKER = @TKR
AND x.[DATE] BETWEEN y.[DATE]-20 AND y.[DATE]
GROUP BY x.DATE
)
答案 0 :(得分:1)
首先,在你的WHERE子句中,你应该替换它:
-- reformatted for readability
WHERE x.[DATE] > (
SELECT TOP 1 z.[DATE] FROM TICKERS z
WHERE z.TICKER = @TKR ORDER BY z.DATE ASC
)+20
AND (DATEDIFF(day, x.[date], GETDATE()) <= 730)
有了这个:
WHERE x.[DATE] > (
SELECT DATEADD(DAY,20,MIN(z.[DATE]))
FROM TICKERS z WHERE z.TICKER = @TKR
)
AND x.[DATE] > DATEADD(DAY,-731,GETDATE())
除非您测试了自己的版本并发现它更快。
除此之外,您可以使用多语句表值函数替换它。例如:
CREATE FUNCTION dbo.GetStdDev (@TKR VARCHAR(10))
RETURNS @results TABLE (
dayno SMALLINT IDENTITY(1,1) PRIMARY KEY
, [date] DATETIME
, [stdev] FLOAT
)
AS BEGIN
DECLARE @min_sysdate DATETIME, @min_tkrdate DATETIME, @rowcount SMALLINT
SET @min_sysdate = DATEADD(DAY,-731,GETDATE())
SET @min_tkrdate = DATEADD(DAY,20,(
SELECT MIN(DATE) FROM TICKERS WHERE TICKER = @TKR))
INSERT @results ([date],[stdev])
SELECT x.[date], ISNULL(STDEV(y.[Close]),0) AS stdev
FROM Tickers x
JOIN Tickers y ON x.[DATE] BETWEEN DATEADD(DAY,-20,y.[DATE]) AND y.[DATE]
WHERE x.[DATE] > @min_tkrdate
AND x.[DATE] > @min_sysdate
AND x.TICKER = @TKR
AND y.TICKER = @TKR
GROUP BY x.[DATE]
SET @rowcount = @@ROWCOUNT
UPDATE @results SET [stdev] = (
SELECT [stdev] FROM @results WHERE dayno = @rowcount-1)
WHERE dayno = @rowcount
RETURN
END