4

我正在尝试计算股票的 3 天移动平均线(实际上是 30 天)交易量。我正在尝试获取最后 3 个日期条目的平均值(而不是今天 - 3 天)。我一直在尝试对 SQL Server 2012 中的 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

示例架构:

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

3 回答 3

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 小提琴演示

最新值:

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 小提琴演示

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

于 2013-03-13T21:18:46.980 回答
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

我发现这对于实际想要完成的事情更加透明。

于 2013-03-14T15:16:13.867 回答
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 的情况下无法处理这种可变分区宽度要求。

于 2013-10-10T19:42:43.427 回答