不同行中的值之间的差异,基于 timediff
Posted
技术标签:
【中文标题】不同行中的值之间的差异,基于 timediff【英文标题】:Diff between values in different rows, based on timediff 【发布时间】:2020-07-09 18:26:48 【问题描述】:MariaDB 版本 10.4.10。
我有一个股票抓取脚本,它每小时获取股票数据并将其插入 mysql 数据库。我想要一种方法来获取每只股票之间的价格差异,例如:
在 2020 年 3 月 25 日 07:00 和 2020 年 3 月 25 日 19:00(12 小时)提取的股票 在 2020 年 3 月 25 日 07:00 和 2020 年 3 月 26 日 07:00(24 小时)提取的股票 在 2020 年 3 月 25 日 08:00 和 2020 年 3 月 25 日 20:00(12 小时)提取的股票 2020-03-25 08:00 和 2020-03-26 08:00 (24 小时) 提取的股票 等等数据库结构如下所示:
stocks( time_fetched DATETIME, name VARCHAR, price INT )
一些示例数据:
**time_fetched name price**
2020-03-25 07:00:00 stock_A 10
2020-03-25 07:00:00 stock_B 14
2020-03-25 08:00:00 stock_A 12
2020-03-25 08:00:00 stock_B 20
...
2020-03-25 19:00:00 stock_A 28
2020-03-25 19:00:00 stock_B 32
2020-03-25 20:00:00 stock_A 40
2020-03-25 20:00:00 stock_B 36
...
2020-03-26 07:00:00 stock_A 12
2020-03-26 07:00:00 stock_B 16
2020-03-26 08:00:00 stock_A 18
2020-03-26 08:00:00 stock_B 16
预期结果:
**time_fetched name current_price price_12h_ago price_24h_ago**
2020-03-25 19:00:00 stock_A 28 10 NULL
2020-03-25 19:00:00 stock_B 32 14 NULL
2020-03-25 20:00:00 stock_A 40 12 NULL
2020-03-25 20:00:00 stock_B 36 20 NULL
2020-03-26 07:00:00 stock_A 12 28 10
2020-03-26 07:00:00 stock_B 16 32 14
2020-03-26 08:00:00 stock_A 18 40 12
2020-03-26 08:00:00 stock_B 16 36 20
目前我正在使用类似这样的 SQL:
WITH prices AS (
SELECT time_fetched, name, price,
LAG(price, 12) OVER(PARTITION BY name ORDER BY time_fetched) AS price_12h_ago,
LAG(price, 24) OVER(PARTITION BY name ORDER BY time_fetched) AS price_24h_ago
FROM stocks
)
SELECT time_fetched, name, price AS current_price, price_12h_ago, price_24h_ago
FROM prices
这是可行的,因为所有股票都获取了所有时间的价格数据。 实际上,有时在几个小时之间存在间隔,并且股票数据库中缺少几个小时的价格数据和一些股票。
这意味着上面获取当前行前 12 行价格的代码并不总是代表当前行前 12 小时。
所以我需要一种方法来根据实际 timediff 获得价格差异。
希望这对任何人都有意义:)
【问题讨论】:
你的所有获取时间都固定了吗? 是的,非常精确。刮板脚本每小时运行一次,但结果可能会在几秒钟内有所不同。 【参考方案1】:您可以使用range()
子句。如果您的时间准确:
SELECT time_fetched, name, price,
MIN(price) OVER (PARTITION BY name
ORDER BY time_fetched
RANGE BETWEEN INTERVAL 12 hour AND INTERVAL 12 hour
) as price_12h_ago,
MIN(price) OVER (PARTITION BY name
ORDER BY time_fetched
RANGE BETWEEN INTERVAL 24 hour AND INTERVAL 24 hour
) as price_24h_ago
FROM stocks;
除非您将分钟和秒设置为精确的0
,否则您可能需要比瞬间更宽的范围。例如:
SELECT time_fetched, name, price,
MIN(price) OVER (PARTITION BY name
ORDER BY time_fetched
RANGE BETWEEN INTERVAL '12:05' HOUR_MINUTE AND INTERVAL '11:55' HOUR_MINUTE
) as price_12h_ago,
MIN(price) OVER (PARTITION BY name
ORDER BY time_fetched
RANGE BETWEEN INTERVAL '24:05' HOUR_MINUTE AND INTERVAL '23:55' HOUR_MINUTE
) as price_24h_ago
FROM stocks;
【讨论】:
谢谢,看来它可以工作。但是,我在测试时确实遇到了一个错误:“检查与您的 MariaDB 服务器版本相对应的手册,以了解在“间隔 12 小时”附近使用的正确语法。不应该是“间隔 12 小时前和当前行之间的范围”吗?这也给了我一个像上面那样的语法错误。不知道为什么。我相信应该可以将 RANGE 和 INTERVAL 与 PARTITION BY 一起使用吗? @thans 。 . . (1) 目的是提前12小时拿到。您也可以使用first_value()
,但您不知道是否真的是 12 小时前。 (2) MySQL 支持带区间的范围。我认为 MariaDB 也可以,但也许不是。以上是关于不同行中的值之间的差异,基于 timediff的主要内容,如果未能解决你的问题,请参考以下文章
计算 distinct 和 join over distinct 之间的差异