SQL使用IN子句查询列表数据时如何为每个项目筛选最新记录?
按股票代码取最新年度财报数据的SQL实现方案
核心需求为对每个股票代码(ticker)分组,取日期最大的一条记录,以下是几种不同场景下的实现方案,全部支持直接在IN子句中传入上百个查询项,无需额外调整逻辑:
1. 通用窗口函数方案(兼容绝大多数支持标准SQL的数据库)
兼容MySQL 8.0+、PostgreSQL、SQL Server、Hive等绝大多数主流数据库,适用范围最广:
SELECT ticker, date FROM ( SELECT ticker, date, ROW_NUMBER() OVER (PARTITION BY ticker ORDER BY date DESC) AS rn FROM company."financials_Income_Statement_yearly" fisy WHERE ticker IN ('IBM.US', 'AAPL.US') -- 直接替换为你的上百个股票代码列表即可 ) t WHERE rn = 1;
说明:通过PARTITION BY按ticker分组,每个分组内按日期倒序排列,取排名第一的记录即为该企业最新的年度数据。
2. PostgreSQL专属优化方案(性能更佳)
如果使用PostgreSQL数据库,可以用更简洁的DISTINCT ON语法,数据量较大时执行效率比窗口函数更高:
SELECT DISTINCT ON (ticker) ticker, date FROM company."financials_Income_Statement_yearly" fisy WHERE ticker IN ('IBM.US', 'AAPL.US') ORDER BY ticker, date DESC;
说明:DISTINCT ON会自动保留每个ticker分组排序后的第一条记录,写法更简洁。
3. 低版本数据库兼容方案(适用于不支持窗口函数的场景,如MySQL 5.x)
如果数据库版本较老不支持窗口函数,可以用先聚合取最大日期、再关联原表的方式实现:
SELECT f.ticker, f.date FROM company."financials_Income_Statement_yearly" f INNER JOIN ( SELECT ticker, MAX(date) AS latest_date FROM company."financials_Income_Statement_yearly" fisy WHERE ticker IN ('IBM.US', 'AAPL.US') GROUP BY ticker ) latest ON f.ticker = latest.ticker AND f.date = latest.latest_date;
注意事项
- 若存在单个ticker同一日期对应多条数据的情况,可以在窗口函数的
ORDER BY后追加其他唯一标识字段排序,保证取到的结果符合预期 - 三种方案均不需要对IN子句的长度做特殊处理,只要数据库本身支持IN子句的参数长度即可正常执行
内容的提问来源于stack exchange,提问作者Lostsoul
相关产品推荐
相关产品推荐

