如何通过使用SQL查询将历史外汇数据从1分钟级别的数据汇总到10分钟级别?

时间:2018-06-27 07:14:02

标签: mysql sql

我有一个表,其中包含历史外汇历史1分钟水平数据,我想根据1分钟水平数据选择10分钟数据。

我的表格如下所示:

    ccy     Time                open     high       low      close
    AUDUSD  2018.03.26 00:00    0.77282  0.77283    0.77265  0.77265
    AUDUSD  2018.03.26 00:01    0.77264  0.77266    0.77261  0.77266
    AUDUSD  2018.03.26 00:02    0.77264  0.77265    0.77259  0.77264
    AUDUSD  2018.03.26 00:03    0.77262  0.77262    0.7726   0.77262
    AUDUSD  2018.03.26 00:04    0.77262  0.77262    0.77262  0.77262
    AUDUSD  2018.03.26 00:05    0.7726   0.7726     0.7726   0.7726
    AUDUSD  2018.03.26 00:06    0.77259  0.77262    0.77259  0.77261
    AUDUSD  2018.03.26 00:07    0.77262  0.77265    0.77262  0.77264
    AUDUSD  2018.03.26 00:08    0.77263  0.77272    0.77262  0.77272
    AUDUSD  2018.03.26 00:09    0.77273  0.77278    0.77271  0.77274
    AUDUSD  2018.03.26 00:10    0.77273  0.77282    0.77271  0.77279
    AUDUSD  2018.03.26 00:11    0.77282  0.77293    0.77281  0.77291
    AUDUSD  2018.03.26 00:12    0.77291  0.77293    0.77287  0.77287
    AUDUSD  2018.03.26 00:13    0.77288  0.77288    0.77288  0.77288
    AUDUSD  2018.03.26 00:14    0.77288  0.77288    0.77277  0.77279
    AUDUSD  2018.03.26 00:15    0.77278  0.77279    0.77255  0.77262
    AUDUSD  2018.03.26 00:16    0.77261  0.77271    0.77261  0.77271
    AUDUSD  2018.03.26 00:17    0.77271  0.77273    0.77264  0.77271
    AUDUSD  2018.03.26 00:18    0.77273  0.77282    0.77273  0.77281
    AUDUSD  2018.03.26 00:19    0.77281  0.77285    0.77281  0.77283

您可以看到时间戳是每1分钟一次,而上面是20分钟的数据样本。

我的预期结果是:

    ccy     Time                open     high       low      close
    AUDUSD  2018.03.26 00:00    0.77282  0.77283    0.77259  0.77274
    AUDUSD  2018.03.26 00:10    0.77273  0.77293    0.77255  0.77283
  • 开盘价必须是时间跨度中每个起点的开盘价,例如从2018.03.26 00:00到2018.03.26 00:09,起点是2018.03.26 00:00 ,因此预期结果开放时间为2018.03.26 00:00的开放时间,即0.77282。

  • 收盘价必须是时间跨度的每个结束点的收盘价,例如从2018.03.26 00:00到2018.03.26 00:09,结束点是2018.03.26 00:09 ,因此预期结果收盘价为2018.03.26 00:09的收盘价,即0.77274。

  • 上限必须是时间跨度的最大值。在高位列中,从2018.03.26 00:00到2018.03.26 00:09,最大值是0.77283,所以我的预期高位是0.77283。

  • 下限必须是时间跨度的最小值。在最低列中,从2018.03.26 00:00到2018.03.26 00:09,最小值为0.77259,所以我的预期最低值为0.77259。

我希望当我有更多数据时,它可以继续循环播放。因此,例如,如果我有1个小时的数据,当我将数据聚合为10分钟的数据时,我希望有60/10 = 6行记录。

我已经为此工作了一段时间,但找不到合适的解决方案,请有人帮忙吗?太谢谢你了!

3 个答案:

答案 0 :(得分:1)

有许多问题尚不清楚。这看起来像是货币换算数据,但未在问题(ccy?)中说明,并且您似乎希望按ccy进行汇总,但未在问题中说明,因此没有表明您希望传递给查询的内容(间隔范围,间隔类型等)。但首先,这是一种方法的示例,我看到的关键问题是获取第一个和最后一个值

drop table if exists t;
create table t(ccy varchar(6),Tm datetime,open decimal(10,5),high decimal(10,5), low decimal(10,5), close decimal(10,5));
insert into t values
(    'AUDUSD',  '2018-03-26 00:00'  ,  0.77282 , 0.77283  ,  0.77265 , 0.77265),
(    'AUDUSD',  '2018-03-26 00:01'  ,  0.77264 , 0.77266  ,  0.77261 , 0.77266),
(    'AUDUSD',  '2018-03-26 00:02'  ,  0.77264 , 0.77265  ,  0.77259 , 0.77264),
(    'AUDUSD',  '2018-03-26 00:03'  ,  0.77262 , 0.77262  ,  0.7726  , 0.77262),
(    'AUDUSD',  '2018-03-26 00:04'  ,  0.77262 , 0.77262  ,  0.77262 , 0.77262),
(    'AUDUSD',  '2018-03-26 00:05'  ,  0.7726  , 0.7726   ,  0.7726  , 0.7726),
(    'AUDUSD',  '2018-03-26 00:06'  ,  0.77259 , 0.77262  ,  0.77259 , 0.77261),
(    'AUDUSD',  '2018-03-26 00:07'  ,  0.77262 , 0.77265  ,  0.77262 , 0.77264),
(    'AUDUSD',  '2018-03-26 00:08'  ,  0.77263 , 0.77272  ,  0.77262 , 0.77272),
(    'AUDUSD',  '2018-03-26 00:09'  ,  0.77273 , 0.77278  ,  0.77271 , 0.77274),
(    'AUDUSD',  '2018-03-26 00:10'  ,  0.77273 , 0.77282  ,  0.77271 , 0.77279);

select ccy, (select open from t t1 where t1.ccy = t.ccy order by t1.tm asc limit 1) periodopen,
                (select close from t t1 where t1.ccy = t.ccy order by t1.tm desc limit 1) period_close,
                max(high) period_high,
                min(low) period_low 
from t
where t.tm between '2018-03-26 00:00' and '2018-03-26 00:10:00'
group by ccy;

+--------+------------+--------------+-------------+------------+
| ccy    | periodopen | period_close | period_high | period_low |
+--------+------------+--------------+-------------+------------+
| AUDUSD |    0.77282 |      0.77279 |     0.77283 |    0.77259 |
+--------+------------+--------------+-------------+------------+
1 row in set (0.00 sec)

答案 1 :(得分:0)

一种方法是对记录进行分组,并使用函数来检索有关每个组的信息。问题是您没有任何要分组的列。

在这种情况下,要在10分钟内创建记录组,可以将“时间”列转换为字符串,并截断最后一位,例如。如果您忽略最后一位,则表中有10条记录的值将为'2018.03.26 00:0'。

关于openclose列,您需要从组内的第一行和最后一行获取值。 Mysql没有FIRSTLAST聚合函数,但是我从answer中学到了可以使用GROUP_CONCAT模拟它们。

select
    ccy,
    SUBSTRING(DATE_FORMAT(Time, '%Y.%m.%d %H:%i'),1,15) as time_group, 
    SUBSTRING_INDEX(GROUP_CONCAT(CAST(open AS CHAR) ORDER BY Time), ',', 1 ) as open,
    MAX(high) as high, 
    MIN(low) as low,
    SUBSTRING_INDEX(GROUP_CONCAT(CAST(close AS CHAR) ORDER BY Time DESC), ',', 1 ) as close
from table_name
group by ccy, time_group;

这是结果

+--------+-----------------+---------+---------+---------+---------+
| ccy    | time_group      | open    | high    | low     | close   |
+--------+-----------------+---------+---------+---------+---------+
| AUDUSD | 2018.03.26 00:0 | 0.77282 | 0.77283 | 0.77259 | 0.77274 |
| AUDUSD | 2018.03.26 00:1 | 0.77273 | 0.77293 | 0.77255 | 0.77283 |
+--------+-----------------+---------+---------+---------+---------+

答案 2 :(得分:0)

这是一项工作-在mssql上测试(我没有mysql),但可能对您有帮助。在mysql中,您只能在字符串concat中更改 TOP 1 DATEPART 和“ + ”符号。

CREATE TABLE [dbo].[T1](
    [F_CCY] [varchar](20) NULL,
    [F_TIME] [datetime] NULL,
    [F_OPEN] [numeric](10, 8) NULL,
    [F_HIGH] [numeric](10, 8) NULL,
    [F_LOW] [numeric](10, 8) NULL,
    [F_CLOSE] [numeric](10, 8) NULL
);

INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26', 0.77282, 0.77283, 0.77265, 0.77265);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:01:00', 0.77264, 0.77266, 0.77261, 0.77266);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:02:00', 0.77264, 0.77265, 0.77259, 0.77264);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:03:00', 0.77262, 0.77262, 0.7726, 0.77262);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:04:00', 0.77262, 0.77262, 0.77262, 0.77262);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:05:00', 0.7726, 0.7726, 0.7726, 0.7726);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:06:00', 0.77259, 0.77262, 0.77259, 0.77261);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:07:00', 0.77262, 0.77265, 0.77262, 0.77264);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:08:00', 0.77263, 0.77272, 0.77262, 0.77272);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:09:00', 0.77273, 0.77278, 0.77271, 0.77274);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:10:00', 0.77273, 0.77282, 0.77271, 0.77279);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:11:00', 0.77282, 0.77283, 0.77265, 0.77265);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:12:00', 0.77264, 0.77266, 0.77261, 0.77266);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:13:00', 0.77264, 0.77265, 0.77259, 0.77264);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:14:00', 0.77262, 0.77262, 0.7726, 0.77262);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:15:00', 0.77262, 0.77262, 0.77262, 0.77262);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:16:00', 0.7726, 0.7726, 0.7726, 0.7726);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:17:00', 0.77259, 0.77262, 0.77259, 0.77261);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:18:00', 0.77262, 0.77265, 0.77262, 0.77264);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:19:00', 0.77263, 0.77272, 0.77262, 0.77272);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:20:00', 0.77273, 0.77278, 0.77271, 0.77274);


SELECT
    T.F_ccy as "ccy"
    , MIN(T.F_TIME) as "Time"
    ,
    (SELECT
        TOP 1 FIRST_VALUE(X.F_OPEN) OVER(ORDER BY X.F_TIME)
    FROM
        T1 X
    WHERE
        X.F_ccy=T.F_ccy
        AND X.F_TIME>=CAST(CAST(CAST(T.F_TIME AS DATE) AS VARCHAR(10)) + ' ' + CAST(DATEPART(HOUR, T.F_TIME) AS VARCHAR(2)) + ':' + CAST((DATEPART(MINUTE, T.F_TIME)/10)*10 AS VARCHAR(2)) AS DATETIME)
        AND X.F_TIME<CAST(CAST(CAST(T.F_TIME AS DATE) AS VARCHAR(10)) + ' ' + CAST(DATEPART(HOUR, T.F_TIME) AS VARCHAR(2)) + ':' + CAST(((DATEPART(MINUTE, T.F_TIME)/10)+1)*10 AS VARCHAR(2)) AS DATETIME)
    ) AS "open"
    ,
    (SELECT
        TOP 1 LAST_VALUE(X.F_OPEN) OVER(ORDER BY X.F_TIME)
    FROM
        T1 X
    WHERE
        X.F_ccy=T.F_ccy
        AND X.F_TIME>=CAST(CAST(CAST(T.F_TIME AS DATE) AS VARCHAR(10)) + ' ' + CAST(DATEPART(HOUR, T.F_TIME) AS VARCHAR(2)) + ':' + CAST((DATEPART(MINUTE, T.F_TIME)/10)*10 AS VARCHAR(2)) AS DATETIME)
        AND X.F_TIME<CAST(CAST(CAST(T.F_TIME AS DATE) AS VARCHAR(10)) + ' ' + CAST(DATEPART(HOUR, T.F_TIME) AS VARCHAR(2)) + ':' + CAST(((DATEPART(MINUTE, T.F_TIME)/10)+1)*10 AS VARCHAR(2)) AS DATETIME)      
        ) AS "close"
    , MAX(T.F_HIGH) as "high"
    , MIN(T.F_LOW) as "low"
FROM
    T1 T
GROUP BY
    T.F_ccy
    , CAST(T.F_TIME AS DATE)
    , DATEPART(HOUR, T.F_TIME)
    , DATEPART(MINUTE, T.F_TIME)/10