-1

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

例如,对于 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 分钟。

4

1 回答 1

0

为了选择具有 5 分钟标记/时间戳的行(如果存在)或最接近的现有条目,您可以使用“(分析)窗口函数”(uses OVER())而不是聚合函数(uses GROUP BY),如下所示:

  1. 将所有行分组为“单独”的5 分钟组
  2. 按与所需时间的接近程度对它们进行排序
  3. 从每个分区中选择第一行。

在这里,我使用OVER子句来创建“窗口框架”并对其中的行进行排序。然后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. 考虑迁移标准 SQL,这是用于查询存储在 BigQuery 中的数据的首选SQL 方言。您可以在单个查询的基础上执行此操作,因此您不必同时迁移所有内容。

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

于 2018-03-20T12:25:27.763 回答