OHCL(Op​​en-high-low-close)T-SQL查询

时间:2017-11-15 14:14:39

标签: sql sql-server tsql

我试图在StockData表上进行OHCL sql查询(SQL Server 2012)。每天有数千行添加到表中,我想获得每天的Open,High,Low和Close数据。

create table sql如下:

  CREATE TABLE [dbo].[StockData](
    [ID] [bigint] IDENTITY(1,1) NOT NULL,
    [StockExchangeID] [bigint] NOT NULL,
    [DataDateTime] [datetime] NOT NULL,
    [ExportCost] [bigint] NOT NULL,
 CONSTRAINT [PK_StockData] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

使用下面的查询,我可以获得高,低和平均,但我很难获得当天的ExportCost的Open(最早的ExportCost基于DataDateTime)和Close(基于DataDateTime的最新ExportCost)。

到目前为止,我的查询如下。如果有更有效的方法,那么欢迎任何建议。

DECLARE @IntervalDays INT, @StartDate DATETIME, @EndDate DATETIME;
SET @IntervalDays = 1;
SET @StartDate = '01/01/2017'
SET @EndDate = '01/01/2018'

-- Create the database table
SELECT 
    StockExchangeID,
    DATEADD(DAY, DATEDIFF(DAY,0,[DataDateTime]) / @IntervalDays * @IntervalDays, 0) AS [DateDay],
    MAX(ExportCost) AS DayHigh, 
    MIN(ExportCost) AS DayLow, 
    AVG(ExportCost) AS DayAverage,
    '??????????' As DayOpen, --Not sure how to get the start price for the day i.e. ExportCost for the first record for that day based on [DataDateTime]
    '??????????' As DatClose
FROM StockData
WHERE [DataDateTime] >= @StartDate AND [DataDateTime] <= @EndDate
GROUP BY DATEADD(DAY, DATEDIFF(DAY,0,[DataDateTime]) / @IntervalDays * @IntervalDays, 0), StockExchangeID
ORDER BY [DateDay]

2 个答案:

答案 0 :(得分:3)

对于旧版本的SQL Server,可以使用相关的子查询:

SELECT 
    StockExchangeID,
    DATEADD(DAY, DATEDIFF(DAY,0,[DataDateTime]) / @IntervalDays * @IntervalDays, 0) AS [DateDay],
    MAX(ExportCost) AS DayHigh, 
    MIN(ExportCost) AS DayLow, 
    AVG(ExportCost) AS DayAverage,
    (SELECT TOP 1 DO.ExportCost FROM StockData AS DO WHERE DO.[DataDateTime] = MIN( A.[DataDateTime] ) ORDER BY ID ASC ) As DayOpen, 
    (SELECT TOP 1 DC.ExportCost FROM StockData AS DC WHERE DC.[DataDateTime] = MAX( A.[DataDateTime] ) ORDER BY ID DESC ) As DatClose
FROM StockData AS A
WHERE [DataDateTime] >= @StartDate AND [DataDateTime] <= @EndDate
GROUP BY DATEADD(DAY, DATEDIFF(DAY,0,[DataDateTime]) / @IntervalDays * @IntervalDays, 0), StockExchangeID
ORDER BY [DateDay]

注意: Order By ID用于以防您拥有超过1条相同日期的记录。

对于较新版本,请查看有关FIRST_VALUE

的@Serg评论

答案 1 :(得分:2)

相信我 - 您可能希望保留此级别的详细数据,但您不希望将其用于一般报告目的。您需要将定价汇总到每天的高/低/收盘/开盘价值并存储它们,因为它们在交易日结束后不会改变(好吧,有时候它们确实如此,但它非常罕见并且不会改变一般方法)。

更进一步 - 您选择主键和聚簇索引可能不是特别有用。您几乎总是在此表中搜索给定的安全性或给定的日期(或日期范围)。在标识列上进行聚类可能很浪费。我还会考虑将日期和时间分成不同的列。日期部分非常重要 - 时间部分可能没有太多使用。如果您要分开日期和时间,您的查询会变得更加简单,因为您只需按日期分组以查找最小值/最大值。通过额外的架构更改(或更好 - 使用后交易聚合表)可以简化查找打开和关闭。