基于2个不同行中的值进行计算

时间:2015-11-16 18:00:45

标签: sql vba ms-access

我在MS Access中有一个表,其股票价格安排如

Ticker1, 9:30:00, $49.01
Ticker1, 9:30:01, $49.08

Ticker2, 9:30:00, $102.02
Ticker2, 9:30:01, $102.15

等等。

我需要做一些计算,我需要比较1行中的价格和前一个价格(如果价格变动在1秒内大于X%,我需要单独报告实例)。

如果我在Excel中这样做,那么这是一个相当简单的公式。我有几百万行数据,所以不能选择。

有关如何在MS Access中执行此操作的任何建议?

我对任何类型的解决方案持开放态度(有或没有SQL或VBA)。

更新的: 我最终试图通过在嵌套循环中使用ADODB.Recordset来遍历我的记录。代码如下。我虽然这是一个好主意,但逻辑适用于一个小桌子(20k行)。但是当我在一个更大的表(3米行)上运行它时,Access膨胀到2GB限制而没有完成任务(因为临时表,原始表的大小更像是~300MB)。将其发布在此处,以防有人使用较小的数据集。

Do While Not rstTickers.EOF
myTicker = rstTickers!ticker
rstDates.MoveFirst

Do While Not rstDates.EOF
myDate = rstDates!Date_Only

    strSql = "select * from Prices where ticker = """ & myTicker & """ and Date_Only = #" & myDate & "#" 'get all prices for a given ticker for a given date
    rst.Open strSql, cn, adOpenKeyset, adLockOptimistic 'I needed to do this to open in editable mode
    rst.MoveFirst
    sPrice1 = rst!Open_Price
    rst!Row_Num = i
    rst.MoveNext

    Do While Not rst.EOF
        i = i + 1
        rst!Row_Num = i
        rst!Previous_Price = sPrice1
        sPrice2 = rst!Open_Price
        rst!Price_Move = Round(Abs((sPrice2 / sPrice1) - 1), 6)
        sPrice1 = sPrice2
        rst.MoveNext
    Loop

i = i + 1
rst.Close
rstDates.MoveNext
Loop

rstTickers.MoveNext
Loop

2 个答案:

答案 0 :(得分:0)

如果数据总是间隔一秒而没有任何毫秒,那么您可以在Ticker ID上将表连接到自身,并将时间偏移一秒。

否则,如果没有某种序列计数器可以加入,那么您需要创建一个。您可以通过执行“排名”查询来执行此操作。有多种方法可以解决这个问题。您可以尝试各自,看看哪种情况在您的情况下最快。

一种方法是使用子查询返回当前行之前的行数。另一种方法是将表连接到自身之前的所有行,并进行分组和计数。这两种方法都会产生相同的结果,但取决于数据的性质以及结构的方式以及您拥有的索引,一种方法比另一种更快。

一旦你有了“等级列”,就会执行第一段中描述的过程,但不是加入时间偏移量,而是加入等级的偏移量。

答案 1 :(得分:0)

我最终将我的数据移动到SQL服务器(它有自己的问题)。我添加了一个像这个

的行号变量(row_num)
i = dataGridView1.RowCount - 1;
if(i<0) // Meaning that the row count was 0
{
return;
}
                cmd.Parameters.AddWithValue("@Id", dataGridView1.Rows[i].Cells[0].Value);
                cmd.Parameters.AddWithValue("@Name", dataGridView1.Rows[i].Cells[1].Value);
                cmd.Parameters.AddWithValue("@Date", dataGridView1.Rows[i].Cells[0].Value);

它对我有用(我认为),因为我的基础数据按照我需要的顺序排列。我已经阅读了足够的评论,你不应该这样做,因为你不知道是什么顺序是存储数据的服务器。

无论如何,在此之后它本身就是一个联盟。花了一些时间来弄清楚语法(我是SQL的新手)。在此处添加SQL以供参考(适用于SQL服务器但不适用于Access)。

ALTER TABLE Prices ADD Row_Num INT NOT NULL IDENTITY (1,1)

顺便说一下,我必须先添加Date_Only这样的列(适用于Access但不适用于SQL服务器)

Update A Set Previous_Price = B.Open_Price
FROM Prices A INNER JOIN Prices B
ON A.Date_Only = B.Date_Only
WHERE ((A.Ticker=B.Ticker) AND (A.Row_Num=B.Row_Num+1));

我认为@Rabbit描述的行号解决方案应该更好(广义上说)。我只是没有时间尝试一下。我花了一整天的时间才能做到这一点。