GET ISNULL от сложной функции - PullRequest
0 голосов
/ 29 октября 2009

У меня есть UDF таблицы SQL, которая получает стандартное отклонение от 20-дневного скользящего среднего значений ... Таблица, из которой она рассчитывает: Tickers ([date] datetime, [close] numeric (7,2))

Функция вычисляет таблицу GetStDev ([date] datetime, stddev numeric (7,2).

Последняя строка столбца stddev всегда NULL (из-за расчета STDEV?) ... Мне нужно заменить значение NULL в последней строке значением из предыдущей строки ([date] -1) .. ... но при этом я должен вычислить весь запрос дважды и выбрать TOP 1 stddev из xxx, и даже в этом случае я не уверен, как написать такой длинный SQL-оператор ... Вот мой UDF таблицы In Line:

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
    )

1 Ответ

1 голос
/ 29 октября 2009

Во-первых, в предложении 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...