-- 需求:取某 ID 附近的前後各 1 條記錄 (SELECT id, title FROM subjects WHERE id > 100 ORDER BY id LIMIT 1) UNION (SELECT id, title FROM subjects WHERE id < 100 ORDER BY id DESC LIMIT 1); -- ERROR 1221 (HY000): Incorrect usage of UNION and ORDER BY
MySQL 語法規定:**UNION 直接包含的 SELECT 不允許單獨使用 ORDER BY**,除非配合 LIMIT。但即使加 LIMIT,單獨 ORDER BY 也會報錯。
SELECT * FROM (
SELECT id, title FROM subjects WHERE id > 100 ORDER BY id LIMIT 1
) AS t1
UNION
SELECT id, title FROM subjects WHERE id < 100 ORDER BY id DESC LIMIT 1;
( ... ) AS t1 中Every derived table must have its own alias| 寫法 | SQL | 結果 |
|---|---|---|
| 直接 UNION + ORDER BY | SELECT ... ORDER BY ... LIMIT 1 UNION SELECT ... ORDER BY ... LIMIT 1 | ❌ 語法錯誤 |
| 第一子查詢加括號無別名 | (SELECT ... ORDER BY ... LIMIT 1) UNION SELECT ... ORDER BY ... LIMIT 1 | ❌ Every derived table must have its own alias |
| 第一子查詢加別名 | (SELECT ... ORDER BY ... LIMIT 1) AS t1 UNION SELECT ... ORDER BY ... LIMIT 1 | ✅ 成功 |
-- 若需最終結果按 id 排序
SELECT * FROM (
SELECT id, title FROM subjects WHERE id > 100 ORDER BY id LIMIT 1
) AS t1
UNION ALL
SELECT id, title FROM subjects WHERE id < 100 ORDER BY id DESC LIMIT 1
ORDER BY id; -- 全局排序 (MySQL 8.0+ 支援 UNION 後 ORDER BY)
WITH next_rec AS (SELECT ... WHERE id > 100 ORDER BY id LIMIT 1),
prev_rec AS (SELECT ... WHERE id < 100 ORDER BY id DESC LIMIT 1)
SELECT * FROM next_rec UNION ALL SELECT * FROM prev_rec;
UNION 中 ORDER BY 限制是 MySQL 歷史語法遺留,**子查詢別名法** 是通用繞過方案。現代應用優先考慮 **CTE (WITH)** 或 **應用層合併**,代碼更清晰、優化器更友好。