首页 文章

SQL Server获取构成聚合的第一行和最后一行

提问于
浏览
1

我有一个表,存储一分钟内价格变动的数据 . 每条记录包含最后一分钟的开放,高,低,关闭和音量

CREATE TABLE TimeBar (
  Instrument varchar(20),
  BarTimeStamp datetimeoffset(7),
  Open decimal(18, 5),
  High decimal(18, 5),
  Low decimal(18, 5),
  Close decimal(18, 5),
  Volume int
)

我想要做的是创建一个查询,我可以将数据聚合到更高的时间帧,例如我希望能够显示每小时的开放,高,低和关闭 .

下面是我的查询到目前为止,我已经设法得到高和低,但你怎么得到开放和关闭?

SELECT MIN(BarTimeStamp) AS TimeStamp,
         MAX(High) AS High,
         MIN(Low) AS Low,
         SUM(Volume) AS Volume
    FROM TimeBar
   WHERE Instrument = 'XYZ'
GROUP BY DATEPART(YEAR, BarTimeStamp), DATEPART(MONTH, BarTimeStamp), DATEPART(DAY, BarTimeStamp), DATEPART(HOUR, BarTimeStamp)

2 回答

  • 1

    首先要做的是按时间范围分组:

    SELECT MIN(BarTimeStamp) AS StartTimeStamp,
             MAX(BarTimeStamp) AS EndTimeStamp
        FROM #TimeBar
       WHERE Instrument = 'TEST'
    GROUP BY DATEPART(YEAR, BarTimeStamp), DATEPART(MONTH, BarTimeStamp), DATEPART(DAY,       BarTimeStamp), DATEPART(HOUR, BarTimeStamp)
    

    在那之后,这是一个问题:

    • 进行连接以获得范围,

    • 做一个加入以获得开始

    • 做一个加入来获得分钟

    • 按原始范围分组以选择所有内容

    我喜欢使用公用表表达式来简化它:

    ;WITH times as (
        SELECT MIN(BarTimeStamp) AS StartTimeStamp,
                 MAX(BarTimeStamp) AS EndTimeStamp
            FROM #TimeBar
           WHERE Instrument = 'TEST'
        GROUP BY DATEPART(YEAR, BarTimeStamp), DATEPART(MONTH, BarTimeStamp), DATEPART(DAY, BarTimeStamp), DATEPART(HOUR, BarTimeStamp)
    )
    SELECT 
        StartTimeStamp as TimeStamp
        ,MIN([first].[Open]) as [Open]
        ,MAX(ranged.High) as High
        ,MAX(ranged.Low) as Low
        ,MIN([last].[Close]) as [Close]
        ,SUM(ranged.Volume) as Volume
    FROM times 
    INNER JOIN #TimeBar ranged ON times.StartTimeStamp <= ranged.BarTimeStamp AND times.EndTimeStamp >= ranged.BarTimeStamp
    INNER JOIN #TimeBar [first] ON times.StartTimeStamp = [first].BarTimeStamp 
    INNER JOIN #TimeBar [last] ON times.EndTimeStamp = [last].BarTimeStamp 
    GROUP BY [times].StartTimeStamp
    

    这是我的测试数据:

    CREATE TABLE #TimeBar (
      Instrument varchar(20),
      BarTimeStamp datetimeoffset(7),
      [Open] decimal(18, 5),
      High decimal(18, 5),
      Low decimal(18, 5),
      [Close] decimal(18, 5),
      Volume int
    )
    
    insert into #TimeBar values ('TEST', '2011-11-21 1:00', 5, 6, 4, 8, 100)
    insert into #TimeBar values ('TEST', '2011-11-21 1:10', 1, 7, 3, 4, 100)
    insert into #TimeBar values ('TEST', '2011-11-21 2:10', 15, 16, 17, 18, 100)
    insert into #TimeBar values ('TEST', '2011-11-21 2:30', 12, 16, 17, 19, 100)
    insert into #TimeBar values ('TEST', '2011-11-21 2:50', 13, 14, 15, 20, 100)
    

    结果是:

    TimeStamp                          Open                                    High                                    Low                                     Close                                   Volume
    ---------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- -----------
    2011-11-21 01:00:00.0000000 +00:00 5.00000                                 7.00000                                 4.00000                                 4.00000                                 200
    2011-11-21 02:10:00.0000000 +00:00 15.00000                                16.00000                                17.00000                                20.00000                                300
    

    注意,我为此使用了临时表,只需将#TimeBar更改为TimeBar即可为真实表更改它 .


    除此之外,我不希望将 Instrurment varchar 视为字段定义 . 你应该使用surrogate key .

  • 1

    使用主查询作为子查询,为每个记录采用最小时间戳和最大时间戳,因此,采用它们各自的开盘价和收盘价 .

    SELECT x.*, TI.Open, TE.Close
    FROM
    (
    SELECT   Instrument,
             MIN(BarTimeStamp) AS TimeStampIni,
             MAX(BarTimeStamp) AS TimeStampEnd,
             MAX(High) AS High,
             MIN(Low) AS Low,
             SUM(Volume) AS Volume
        FROM TimeBar
    GROUP BY Instrument, DATEPART(YEAR, BarTimeStamp), DATEPART(MONTH, BarTimeStamp), DATEPART(DAY, BarTimeStamp), DATEPART(HOUR, BarTimeStamp)
    ) x
    inner join TimeBar TI on ti.Instrument = x.Instrument AND TI.BarTimeStamp = x.TimeStampIni
    inner join TimeBar Te on te.Instrument = x.Instrument AND Te.BarTimeStamp = x.TimeStampEnd
    

相关问题