不同行中的值之间的差异,基于 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 之间的差异

如何计算同一张表中 2 个不同行之间的时间差?

如何在不使用临时表的情况下检索当前行和先前行的值之间的值差异?

mysql:一列中的值之间的差异

将不同行中的值合并为一列