Sql server 每日每台股票的移动平均数

Sql server 每日每台股票的移动平均数,sql-server,sql-server-2012,moving-average,Sql Server,Sql Server 2012,Moving Average,我试图计算,比如说,股票的3天移动平均(实际上是30天)成交量。 我试图得到最后3个日期条目的平均值(而不是今天—3天)。我一直在尝试在SQLServer2012中使用rownumber,但没有成功。有人能帮忙吗。下面是一个模板模式,以及我对SQL的垃圾尝试。我在group by中使用了以下SQL的各种版本,但仍然不起作用。非常感谢 select dt_eod, ticker, volume from ( select dt_eod, ticker, avg(volume) row

我试图计算,比如说,股票的3天移动平均(实际上是30天)成交量。 我试图得到最后3个日期条目的平均值(而不是今天—3天)。我一直在尝试在SQLServer2012中使用rownumber,但没有成功。有人能帮忙吗。下面是一个模板模式,以及我对SQL的垃圾尝试。我在group by中使用了以下SQL的各种版本,但仍然不起作用。非常感谢

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

每行平均三天:

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

最新值:

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


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

您提到的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

我发现这比实际要完成的工作要透明得多。

您可能想看看这里介绍的另一种技术:

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


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

如果您创建了一个包含字段Year和BusinessDay(从1到250左右)的Calandar表,那么您可以将卷加入其中,并在BusinesDay(getdate())-3到BusinesDay(getdate())之间求平均值。确实不错。但是,使用
交叉应用
而不是
外部应用
将产生相同的输出,并可能产生更好的执行计划。公平点是,当每个应用都连接到自身时,很难避免连接到某个对象<代码>外部应用在这种情况下显然过于谨慎!
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