基于时间戳准确查询数据库

时间:2018-03-07 20:17:58

标签: mysql sql google-bigquery time-series legacy-sql

在Google Big Query数据集中查询价格与时间时,我目前遇到准确性问题。我想要的是每五分钟一次资产的价格,但是有些资产在一分钟内有一个空行。

例如,对于两个加密货币的VEN与ICX,可能会有一段时间价格数据不可用于特定秒。在我的查询中,我每300秒查询一次数据库并获取价格数据,但有些资产没有时间戳5分0秒。因此,我想得到最后的已知价格:使用的好价格是4分58秒。

我现在的查询是:

SELECT MIN(price) AS PRICE, timestamp
FROM [coin_data] 
WHERE coin="BTCUSD" AND TIMESTAMP_TO_SEC(timestamp) % 300 = 0
GROUP BY timestamp
ORDER BY timestamp ASC

此查询会在特定位置产生这种差距:

Row((10339.25, datetime.datetime(2018, 2, 26, 21, 55, tzinfo=<UTC>)))

Row((10354.62, datetime.datetime(2018, 2, 26, 22, 0, tzinfo=<UTC>)))

Row((10320.0, datetime.datetime(2018, 2, 26, 22, 10[should be 5 for 5 min], tzinfo=<UTC>)))

这个在最后一栏不应该是10,因为那是分钟的地方,它应该是5分钟。

1 个答案:

答案 0 :(得分:0)

要选择具有5分钟标记/时间戳(如果存在)或最近的现有条目的行,您可以使用"(analytic) window functions"(使用OVER())代替aggregate functions (使用GROUP BY),如下所示:

  1. 将所有行分组到&#34;分开&#34; 5分钟组
  2. 按接近期望的时间排序
  3. 从每个分区中选择第一行。
  4. 这里我使用OVER子句创建&#34;窗口框架&#34; 并对其中的行进行排序。然后RANK()对每个窗口框架中的所有行进行编号。

    标准SQL

    WITH
      data AS (
      SELECT *,
        CAST(FLOOR(UNIX_SECONDS(timestamp)/300) AS INT64) AS timegroup
      FROM
        `coin_data` )
    SELECT min(price) as min_price, timestamp
    FROM
     (SELECT *, RANK() OVER(PARTITION BY timegroup ORDER BY timestamp ASC) AS rank
      FROM data)
    WHERE rank = 1
    group by timestamp
    ORDER BY timestamp ASC
    

    旧版SQL

    SELECT MIN(price) AS min_price, timestamp
    FROM (
      SELECT *,
    RANK() OVER(PARTITION BY timegroup ORDER BY timestamp ASC) AS rank,
      FROM (
        SELECT *,
          INTEGER(FLOOR(TIMESTAMP_TO_SEC(timestamp)/300)) AS timegroup
        FROM [coin_data]) AS data )
    WHERE rank = 1
    GROUP BY timestamp
    ORDER BY timestamp ASC
    

    您似乎在同一时间戳上有很多价格,在这种情况下,您可能希望在OVER子句中添加另一个字段。

    OVER(PARTITION BY timegroup, exchange ORDER BY timestamp ASC)
    

    注意:

    1. 考虑migrating标准SQL ,这是用于查询存储在BigQuery中的数据的首选 SQL方言。您可以在单个查询的基础上执行此操作,因此您不必同时迁移所有内容。

    2. 我的想法是提供一个通用查询来说明原理,因此我不会过滤空行,因为它不清楚它们是空的还是空字符串而且它是&#39 ;答案不是真的必要。