这里到处都有这样的问题,所以让我指出一下我特别需要帮助的地方。
我已经在SQL中看到了使用Oracle Analytic函数,MSSQL应用或其他各种方法的移动平均值。我也看到过自我联接(平均每一天的一次加入,例如How do you create a Moving Average Method in SQL?)。
我很好奇是否有一种方法(仅使用自联接)在SQL中执行此操作(最好是oracle,但由于我的问题仅适用于连接,因此任何RDBMS都应该可以实现)。这种方式必须是可扩展的(对于20或100天的移动平均线,与我上面研究的链接相比,后者需要在移动平均线中每天加入一次)。
我的想法是
select customer, a.tradedate, a.shares, avg(b.shares)
from trades a, trades b
where b.tradedate between a.tradedate-20 and a.tradedate
group by customer, a.tradedate
但是当我在过去尝试它时它没有用。更具体地说,我正在尝试一个更小但相似的例子(5天平均而不是20天)与这个小提琴演示并且无法找出我出错的地方。 http://sqlfiddle.com/#!6/ed008/41
select a.ticker, a.dt_date, a.volume, avg(b.volume)
from yourtable a, yourtable b
where b.dt_date between a.dt_date-5 and a.dt_date
and a.ticker=b.ticker
group by a.ticker, a.dt_date, a.volume
答案 0 :(得分:0)
http://sqlfiddle.com/#!6/ed008/45似乎就是您所需要的。
select a.ticker,
a.dt_date,
a.volume,
(select avg(cast(b.volume as float))
from yourtable b
where b.dt_date between a.dt_date-5 and a.dt_date
and a.ticker=b.ticker)
from yourtable a
order by a.ticker, a.dt_date
不是连接而是子查询
答案 1 :(得分:0)
我没有看到你的第二个查询有什么问题,我认为这不是你期望的唯一原因是因为音量字段是一个整数数据类型所以当你计算平均值时,结果输出也将是一个整数数据类型。对于平均值,您必须转换它,因为结果不一定是整数(整数):
select a.ticker, a.dt_date, a.volume, avg(cast(b.volume as float))
from yourtable a
join yourtable b
on a.ticker = b.ticker
where b.dt_date between a.dt_date - 5 and a.dt_date
group by a.ticker, a.dt_date, a.volume
<强>小提琴:强> http://sqlfiddle.com/#!6/ed008/48/0(感谢@DaleM for DDL)
我不知道为什么你会这样做而不是分析功能,特别是因为你提到想要在Oracle(具有分析功能)中这样做。如果您的首选数据库是MySQL或没有分析函数的数据库,则会有所不同。
只是为了补充答案,这就是使用分析函数在Oracle中实现相同结果的方法。请注意PARTITION BY如何充当您在股票代码上使用的联接。这会分割结果,以便在多个代码中共享的相同日期不会干扰。
select ticker,
dt_date,
volume,
avg(cast(volume as decimal)) over( partition by ticker
order by dt_date
rows between 5 preceding
and current row ) as mov_avg
from yourtable
order by ticker, dt_date, volume
<强>小提琴:强> http://sqlfiddle.com/#!4/0d06b/4/0
分析函数的运行速度可能会快得多。