MySQL `ORDER BY` 支持多字段,按聲明順序依次排序:先按第一字段,相同則按第二字段,以此類推。
SELECT * FROM table_name ORDER BY field1, field2;
-- field1 降序,field2 升序 (默認)
SELECT * FROM table_name ORDER BY field1 DESC, field2 ASC;
-- 等價簡寫 (ASC 可省略)
SELECT * FROM table_name ORDER BY field1 DESC, field2;
-- 銷量降序、價格升序 (銷量同則價格低者優先)
SELECT * FROM products ORDER BY sales_volume DESC, price ASC;
BBS/文章列表常見需求:置頂文章始終展示在最前,其次按時間倒序。
CREATE TABLE posts (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(200) NOT NULL,
content TEXT,
priority TINYINT NOT NULL DEFAULT 0 COMMENT '置頂權重:0=普通, 1=置頂, 2=全局置頂...',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- 聯合索引支持 ORDER BY priority DESC, create_time DESC
INDEX idx_priority_time (priority DESC, create_time DESC)
) ENGINE=InnoDB;
SELECT * FROM posts
ORDER BY priority DESC, create_time DESC;
深分頁 `LIMIT 10000, 20` 配合 `ORDER BY` 會掃描大量行。利用覆蓋索引 + 子查詢優化:
-- 1. 覆蓋索引只掃描索引獲取 ID
SELECT id FROM posts ORDER BY priority DESC, create_time DESC LIMIT 10000, 20;
-- 2. 回表查詳細信息
SELECT * FROM posts WHERE id IN (上述子查詢) ORDER BY priority DESC, create_time DESC;
| 誤區 | 後果 | 正確做法 |
|---|---|---|
| `ORDER BY RAND()` 隨機排序 | 全表掃描 + 臨時表 + 文件排序,極慢 | 應用層隨機 ID / `ORDER BY RAND()` 限制小表 |
| 排序字段無索引 | Using filesort,大數據量極慢 | 建立聯合索引匹配 ORDER BY 順序 |
| `ORDER BY field1 DESC, field2 ASC` 索引方向不匹配 | MySQL 8.0 前無法使用索引降序掃描 | 8.0+ 支持降序索引 `INDEX idx (f1 DESC, f2 ASC)`;舊版統一用 ASC 應用層反轉 |
| 置頂用 `is_top=1` 但無索引 | 全表掃描 | 建立 `INDEX idx_top_time (is_top, create_time)` |