1

我正在研究一个汇总财务数据观察的数据库(以货币对 USDCAD 为例)。

财务数据作为观察数据出现。我没有设置观察的日期和时间,因为它是由数据提供者确定的。

我的表如下所示: CREATE TABLE observations (symbol varchar(32) not null, datetime datetime not null, value decimal(20, 10) not null);

当我需要在没有特定观察的情况下获取系列的值时,就会出现问题。例如,我可能想在上午 10:30:15 对我们以加元销售的某种产品重新定价。

但是,我可能不会在上午 10:30:15 准确地观察到 USDCAD。这将需要我做一个加权平均来得到那个确切时间的观察结果。

这有点麻烦,但可能。更大的问题是 - 如果我有一张包含我们产品每秒的美元价格的表格,并且我想以 USDCAD 重新定价每个产品价格观察(每秒)(其中有随机定时的观察),我不能想办法在没有疯狂子查询的情况下做到这一点。

我在这里最好的选择是什么?插入值时,是否也可以更好地计算 USDCAD 系列的每秒观测值?

4

1 回答 1

3
  1. @time通过应用线性插值获得加权平均观测值:

    SELECT p0.y + (UNIX_TIMESTAMP(@time)-p0.x) * (p1.y-p0.y) / (p1.x-p0.x)
    FROM
      (
        SELECT   `value`                     AS y
          ,       UNIX_TIMESTAMP(`datetime`) AS x
        FROM     `observations`
        WHERE    `datetime` <= @time
        ORDER BY `datetime` DESC
        LIMIT    1
      ) p0,
      (
        SELECT   `value`                     AS y
          ,       UNIX_TIMESTAMP(`datetime`) AS x
        FROM     `observations`
        WHERE    `datetime` >= @time
        ORDER BY `datetime` ASC
        LIMIT    1
      ) p1;
    
  2. VIEW使用最新汇率以 CAD 价格创建您的产品:

    CREATE VIEW `productsCAD` AS
      SELECT `products`.*
        ,    `products`.`price` * `exchange`.`value` AS `priceCAD`
      FROM   `products`
        , (
          SELECT   `value`
          FROM     `observations`
          ORDER BY `datetime` DESC
          LIMIT    1
        ) AS `exchange`;
    

更新

要获得多个预定义时间的插值价格(假设存储为名为的表DATETIME中的列中的值),您需要使用子查询首先获取前一个和紧随其后的观察时间,然后将这些时间与观察结果连接起来再次表以获取相应的值:timetimes

SELECT time, p0.y + IFNULL((unixtime-p0.x) * (p1.y-p0.y) / (p1.x-p0.x), 0) AS value
FROM
  (
    SELECT
          time,
          UNIX_TIMESTAMP(`time`)               AS `unixtime`,
      MAX(UNIX_TIMESTAMP(`before`.`datetime`)) AS `prevTime`,
      MIN(UNIX_TIMESTAMP( `after`.`datetime`)) AS `nextTime`
    FROM
      `times`
      JOIN (SELECT `datetime` FROM `observations`)
        AS `before` ON (`before`.`datetime` <= `time`)
      JOIN (SELECT `datetime` FROM `observations`)
        AS `after`  ON ( `after`.`datetime` >= `time`)
    GROUP BY `time`
  ) AS `matches`
  JOIN (
    SELECT
      UNIX_TIMESTAMP(`datetime`) AS x,
      `value`                    AS y
    FROM `observations`
  ) AS p0 ON (p0.x = `matches`.`prevTime`)
  JOIN (
    SELECT
      UNIX_TIMESTAMP(`datetime`) AS x,
      `value`                    AS y
    FROM `observations`
  ) AS p1 ON (p1.x = `matches`.`nextTime`);

如果要在查询中指定所需的时间(而不是使用预定义的表times),请将对的引用替换为times使用动态构建此类表的子查询UNION

SELECT time, p0.y + IFNULL((unixtime-p0.x) * (p1.y-p0.y) / (p1.x-p0.x), 0) AS value
FROM
  (
    SELECT
          time,
          UNIX_TIMESTAMP(`time`)               AS `unixtime`,
      MAX(UNIX_TIMESTAMP(`before`.`datetime`)) AS `prevTime`,
      MIN(UNIX_TIMESTAMP( `after`.`datetime`)) AS `nextTime`
    FROM
      (
                  SELECT '2012-05-02 19:20:00' AS `time`
        UNION ALL SELECT '2012-05-02 19:20:05'
        UNION ALL SELECT '2012-05-02 19:20:10'
        UNION ALL SELECT '2012-05-02 19:20:15'
        -- etc.
      ) AS `times`
      JOIN (SELECT `datetime` FROM `observations`)
        AS `before` ON (`before`.`datetime` <= `time`)
      JOIN (SELECT `datetime` FROM `observations`)
        AS `after`  ON ( `after`.`datetime` >= `time`)
    GROUP BY `time`
  ) AS `matches`
  JOIN (
    SELECT
      UNIX_TIMESTAMP(`datetime`) AS x,
      `value`                    AS y
    FROM `observations`
  ) AS p0 ON (p0.x = `matches`.`prevTime`)
  JOIN (
    SELECT
      UNIX_TIMESTAMP(`datetime`) AS x,
      `value`                    AS y
    FROM `observations`
  ) AS p1 ON (p1.x = `matches`.`nextTime`);
于 2012-05-02T07:55:04.040 回答