2013-03-13 3 views
4

Я пытаюсь вычислить, скажем, 3-дневный скользящий средний (на самом деле 30-дневный) объем для акций. Я пытаюсь получить среднее значение из последних 3 записей даты (а не сегодня - 3 дня). Я пытался что-то сделать с rownumber в SQL Server 2012, но без успеха. Может кто поможет. Ниже приведена схема шаблона, и моя попытка мусора в SQL. У меня есть различные воплощения ниже SQL с группой, но все еще не работает. Большое спасибо!Скользящее среднее для TICKER за каждый день

select dt_eod, ticker, volume 
from 
(
    select dt_eod, ticker, avg(volume) 
    row_number() over(partition by dt_eod order by max_close desc) rn 
    from mytable 
) src 
where rn >= 1 and rn <= 3 
order by dt_eod 

Пример схемы:

CREATE TABLE yourtable 
    ([dt_date] int, [ticker] varchar(1), [volume] int); 

INSERT INTO yourtable 
    ([dt_date], [ticker], [volume]) 
VALUES 
    (20121201, 'A', 5), 
    (20121201, 'B', 7), 
    (20121201, 'C', 6), 
    (20121202, 'A', 10), 
    (20121202, 'B', 8),  
    (20121202, 'C', 7), 
    (20121203, 'A', 10),  
    (20121203, 'B', 87),  
    (20121203, 'C', 74), 
    (20121204, 'A', 10),  
    (20121204, 'B', 86), 
    (20121204, 'C', 67), 
    (20121205, 'A', 100), 
    (20121205, 'B', 84), 
    (20121205, 'C', 70),  
    (20121206, 'A', 258), 
    (20121206, 'B', 864), 
    (20121206, 'C', 740); 
+0

Если вы создали таблицу Calandar с полями Year и BusinessDay (начиная от 1 до 250 или около того), то вы можете присоединиться к своим томам к ней и в среднем по BusinesDay (getdate()) - 3 в BusinesDay (getdate()) , –

ответ

3

Три дня в среднем для каждой строки:

with top3Values as 
(
    select t.ticker, t.dt_date, top3.volume 
    from yourtable t 
    outer apply 
    (
     select top 3 top3.volume 
     from yourtable top3 
     where t.ticker = top3.ticker 
     and t.dt_date >= top3.dt_date 
     order by top3.dt_date desc 
    ) top3 
) 
select ticker, dt_date, ThreeDayVolume = avg(volume) 
from top3Values 
group by ticker, dt_date 
order by ticker, dt_date 

SQL Fiddle demo.

Последнее значение:

with tickers as 
(
    select distinct ticker from yourtable 
), top3Values as 
(
    select t.ticker, top3.volume 
    from tickers t 
    outer apply 
    (
     select top 3 top3.volume 
     from yourtable top3 
     where t.ticker = top3.ticker 
     order by dt_date desc 
    ) top3 
) 
select ticker, ThreeDayVolume = avg(volume) 
from top3Values 
group by ticker 
order by ticker 

SQL Fiddle demo.

Реалистично вам не нужно будет создавать линеечки КТР для второго запроса, как вы бы основывая это на [ticker] столе, и вы, вероятно, есть какая-то date параметра в запросе, но, надеюсь, это вы попадете на правильный путь.

+0

Отлично - он работает, просто нужно понять его полностью сейчас! – SQLseeker

+0

Ницца действительно. Однако использование «cross apply» вместо «external apply» приведет к тому же выводу и может привести к лучшему плану выполнения. –

+0

Справедливая точка, трудно избежать присоединения к чему-то, когда каждый присоединяется к себе ... «Наружное применение» явно перестраховно в этом случае! –

2

Вы упомянули SQL 2012, что означает, что вы можете использовать гораздо более простую парадигму.

select dt_date, ticker, avg(1.0*volume) over (
    partition by ticker 
    order by dt_date 
    ROWS BETWEEN 2 preceding and current row 
) 
from yourtable 

Я нахожу это гораздо более прозрачным относительно того, что на самом деле пытается достичь.

1

Возможно, вы захотите посмотреть еще одну технику, которая представлена ​​здесь: SQL-Server Moving Averages set-based algorithm with flexible window-periods and no self-joins.

Алгоритм довольно быстрый (гораздо быстрее, чем APPLY, и не ухудшается в производительности, например APPLY, по мере расширения окна данных), легко адаптируется к вашему требованию, работает с pre-SQL2012 и преодолевает ограничения SQL -2012, которая требует жесткого кодирования ширины окна в предложении OVER/PARTITION-BY.

Для приложения типа фондового рынка с подвижными средними ценами, общее требование, позволяющее пользователю , варьировать количество точек данных, включенных в среднее (из пользовательского интерфейса, например, позволяя пользователю выбрать 7 дней, 30 дней, 60 дней и т. д.), а предложение OVER SQL-2012 не может обрабатывать эту переменную ширины раздела без динамического SQL.

Смежные вопросы