如何在MySQL中选择近月到期合约数据?
筛选MySQL数据集中近月到期数据的方法
首先得明确:你的需求应该是针对每个Date(交易日),筛选出该日期下到期日最早(近月)的那条收盘价记录对吧?结合你给的示例数据,我来一步步教你实现。
第一步:确保日期字段可正确比较
你的示例里Date和Expiry是类似20-Mar-18的字符串格式,直接用字符串比较会出问题(比如"01-Apr-18"会被错误判定为比"28-Mar-18"小,因为字母A在M前面)。所以首先要把这些字符串转成MySQL的DATE类型,用STR_TO_DATE()函数,格式符'%d-%b-%y'刚好匹配你的日期格式:
STR_TO_DATE(Date, '%d-%b-%y') AS trade_date, STR_TO_DATE(Expiry, '%d-%b-%y') AS expiry_date
方法一:用窗口函数(MySQL 8.0及以上版本推荐)
窗口函数是最简洁高效的方式,用ROW_NUMBER()给每个交易日的记录按到期日升序编号,然后取编号为1的那条(就是近月到期的):
SELECT trade_date, expiry_date, Close FROM ( SELECT STR_TO_DATE(Date, '%d-%b-%y') AS trade_date, STR_TO_DATE(Expiry, '%d-%b-%y') AS expiry_date, Close, ROW_NUMBER() OVER (PARTITION BY STR_TO_DATE(Date, '%d-%b-%y') ORDER BY STR_TO_DATE(Expiry, '%d-%b-%y') ASC) AS rn FROM futures_data ) AS ranked_data WHERE rn = 1;
PARTITION BY:按交易日分组,把同一天的记录归为一组ORDER BY:每组内按到期日从小到大排序,让近月的记录排第一rn = 1:筛选出每组的第一条记录,也就是对应近月到期的数据
方法二:兼容旧版本MySQL(5.x及以下)
如果你的MySQL版本不支持窗口函数,可以用子查询先找到每个交易日的最小到期日,再关联原表获取对应的收盘价:
SELECT STR_TO_DATE(fd.Date, '%d-%b-%y') AS trade_date, STR_TO_DATE(fd.Expiry, '%d-%b-%y') AS expiry_date, fd.Close FROM futures_data fd INNER JOIN ( SELECT Date, MIN(STR_TO_DATE(Expiry, '%d-%b-%y')) AS min_expiry FROM futures_data GROUP BY Date ) AS min_expiry_data ON fd.Date = min_expiry_data.Date AND STR_TO_DATE(fd.Expiry, '%d-%b-%y') = min_expiry_data.min_expiry;
- 子查询
min_expiry_data:先算出每个交易日对应的最早到期日 - 内关联原表:找到和这个最早到期日匹配的记录,就是你要的近月数据
额外提示
如果你的表中已经把Date和Expiry字段存成DATE类型(而不是字符串),那可以去掉所有STR_TO_DATE()转换,直接用字段名即可,查询效率会更高。
内容的提问来源于stack exchange,提问作者Rusty Banks
相关产品推荐
相关产品推荐

