OHCL (Open-high-low-close) T-SQL 查询
Posted
技术标签:
【中文标题】OHCL (Open-high-low-close) T-SQL 查询【英文标题】:OHCL (Open-high-low-close) T-SQL Query 【发布时间】:2017-11-15 14:14:38 【问题描述】:我正在尝试对 StockData 表执行 OHCL sql 查询 (SQL Server 2012)。每天有数千行添加到表中,我想获取每天的开盘价、最高价、最低价和收盘价数据。
创建表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 的打开(基于 DataDateTime 的最早 ExportCost)和关闭(基于 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]
【问题讨论】:
哪个版本的sql server?/ @IntervalDays * @IntervalDays
应该达到什么目的?
Sql-server 2012 及更高版本支持 FIRST_VALUE、LAST_VALUE。检查答案***.com/questions/41840829/… 以查看 GROUP BY 的用法
SQL Server 2012.
【参考方案1】:
对于旧版本的 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 条具有相同日期的记录。
对于较新的版本,请查看@Serg 关于FIRST_VALUE
的评论
【讨论】:
这提供了正确的结果 - 谢谢。如果表中有很多行,CTE 或其他替代查询会使其更高效吗? 你最大的表现违规者将是GROUP BY DATEADD(DAY, DATEDIFF(DAY,0,[DataDateTime]) / @IntervalDays * @IntervalDays, 0)
。你仍然没有回复我原来的评论,为什么你乘以同一个变量然后除以相同的变量。
Alex - 我从另一个查询中复制了那段代码,我已经拆分并将库存时间分组为每天 15 分钟的间隔。因为它是我当前的查询,它什么都不做,我将删除它。【参考方案2】:
相信我 - 您可能希望保留此级别的详细数据,但不想将其用于一般报告目的。您需要将定价汇总为每天的最高/最低/收盘/开盘价并存储它们,因为它们在交易日结束后不会改变(嗯,有时它们会改变,但这种情况非常罕见并且不会改变一般方法)。
更进一步 - 您选择的主键和聚集索引可能不是特别有用。您几乎总是在此表中搜索给定证券或给定日期(或日期范围)。在标识列上进行聚类可能很浪费。我还会考虑将日期和时间分成单独的列。日期部分非常重要——时间部分可能用的不多。如果您要将日期和时间分开,您的查询会变得更加简单,因为您只需按日期分组即可找到最小值/最大值。通过额外的架构更改(或更好 - 使用交易后聚合表)可以简化查找打开和关闭。
【讨论】:
我意识到这一点,但现在我正在制作原型,我需要一些快速而肮脏的东西。我们确实设想了一个计划的作业/服务将聚合数据推送到历史表以便更好地查询。无论哪种方式,我仍然需要解决查询。谢谢大家!以上是关于OHCL (Open-high-low-close) T-SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章