業務常需獲取「倒數第 N 條」記錄,以倒數第二條為例,介紹三種通用寫法。
SELECT * FROM tablename ORDER BY id DESC LIMIT 1, 1;
原理:LIMIT offset, count 跳過 offset 行,取 count 行。倒序後第 0 行是最新,第 1 行即倒數第二條。
SELECT * FROM tablename a WHERE (SELECT COUNT(*) FROM tablename b WHERE a.id < b.id) = 1;
原理:統計比當前行 ID 大的記錄數,等於 1 即為倒數第二條。適用於無自增主鍵或需按業務字段排序的場景。
// 類 Hibernate/ActiveRecord 風格
last = HolderChangeHistory.find_by_sql(["
SELECT * FROM holder_change_histories
WHERE treasure_id = ?
ORDER BY id DESC
LIMIT 1, 1
", @hch.treasure_id]);
| 方法 | 適用場景 | 性能 | 備註 |
|---|---|---|---|
| LIMIT offset | 有自增/唯一排序列、數據量大 | ⭐⭐⭐⭐⭐ | 利用索引掃描,極快 |
| 子查詢計數 | 無自增 ID、複雜排序 | ⭐⭐⭐ | 全表掃描,大表慎用 |
| 雙重排序 | 舊版本不支持 LIMIT offset | ⭐⭐ | 需兩次排序,效率低 |
最佳實踐:表設計時確保有自增主鍵或唯一遞增排序列,直接使用 ORDER BY id DESC LIMIT 1,1。