每天的移动平均PER TICKER

时间:2013-03-13 20:32:34

标签: sql-server sql-server-2012 moving-average

我正在试图计算3天移动平均线(实际为30天)的库存量。 我想要获得最近3个日期条目的平均值(而不是今天的3天)。我一直在尝试使用SQL Server 2012中的rownumber做一些事情,但没有成功。任何人都可以帮忙。下面是一个模板架构,我的垃圾尝试SQL。我有以下SQL的各种版本与group by,但仍然无法正常工作。非常感谢!

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);

3 个答案:

答案 0 :(得分: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

实际上,您不需要为第二个查询创建代码CTE,因为您将基于[ticker]表,并且您可能有某种date参数在查询中,但希望这会让你走上正确的轨道。

答案 1 :(得分: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

我发现实际上要完成的事情要透明得多。

答案 2 :(得分:1)

您可能希望查看此处提供的另一种技术:SQL-Server Moving Averages set-based algorithm with flexible window-periods and no self-joins

该算法速度非常快(比APPLY快得多,并且不会像APPLY那样在数据点窗口扩展时降低性能),可以轻松适应您的要求,适用于SQL2012之前,并克服SQL的限制 - 2012年的窗口功能需要在OVER / PARTITION-BY子句中对窗口宽度进行硬编码。

对于具有移动价格平均值的股票市场类型应用程序,通常要求允许用户改变平均值中包含的数据点数量(来自UI选择,比如允许用户选择7天,30天,60天等,而SQL-2012的OVER子句无法在没有动态SQL的情况下处理这个变量分区宽度要求。