使用ROW_NUMBER()窗口函数结合ORDER BY最新时间字段,能高效获取每组最新的记录:
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Category ORDER BY UpdateDate DESC) AS rn
FROM YourTable
) t WHERE rn = 1;
使用CTE实现高效最新数据获取
WITH LatestRecords AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY CreatedDate DESC) AS RowNum
FROM Orders
)
SELECT * FROM LatestRecords WHERE RowNum = 1;
索引优化是关键
在ORDER BY字段上创建合适的索引:在UserID和CreatedDate字段组合上创建索引,能让窗口函数的排序过程利用索引,避免全表排序。
NOT EXISTS方法
SELECT * FROM Orders o1
WHERE NOT EXISTS (
SELECT 1 FROM Orders o2
WHERE o2.UserID = o1.UserID
AND o2.CreatedDate > o1.CreatedDate
);
使用TIMESTAMP字段
为表添加rowversion类型字段,每行更新时自动变化:
ALTER TABLE YourTable ADD SysChangeVersion rowversion;
然后通过比较SysChangeVersion值判断最新记录。
分区表优化
按日期分区表,查询时只扫描最新分区,大幅提升性能。创建分区函数和方案后,最新数据查询只需访问最近的分区。
查询提示使用
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Date DESC) rn
FROM TableName WITH (NOLOCK)
) t WHERE rn=1 OPTION (MAXDOP 1);
FAQ
Q: 窗口函数性能如何?
A: 比子查询快,SQL Server能优化执行计划,尤其有合适索引时。
Q: 百万级数据怎么处理?
A: 必须建索引,避免全表扫描;考虑分页或按分区处理。
Q: 怎么避免表锁?
A: 用WITH(NOLOCK)读未提交数据,或用快照隔离级别。
Q: 跨库最新数据怎么取?
A: 用Linked Server,先汇总到临时表再窗口函数处理。