-- 壓縮寫法 (難維護)
SELECT id,name,email FROM users WHERE status=1 AND created_at>'2023-01-01' ORDER BY id DESC LIMIT 20;
-- 結構化寫法 (推薦)
SELECT
`id`,
`name`,
`email`
FROM `users`
WHERE `status` = 1
AND `created_at` > '2023-01-01'
ORDER BY `id` DESC
LIMIT 20;
sql-formatter / IDE 插件自動格式化
-- ❌ 多個 OR
SELECT * FROM articles WHERE category_id = 1 OR category_id = 3 OR category_id = 5;
-- ✅ IN 列表 (優化器可優化為 range 訪問)
SELECT * FROM articles WHERE category_id IN (1, 3, 5);
-- ✅ 子查詢 (動態值)
SELECT * FROM articles WHERE category_id IN (SELECT id FROM categories WHERE parent_id = 0);
IN 列表常數會優化為二分查找,大列表 (>1000) 建議用臨時表/關聯NOT IN 含 NULL 陷阱,改用 NOT EXISTS
-- 單字段拼接
SELECT CONCAT(`id`, '-', `title`) AS `id_title` FROM articles WHERE id = 1;
-- 結果: "1-MySQL 優化指南"
-- 多字段構造 JSON 片段 (MySQL 5.7+ JSON_OBJECT 更好)
SELECT CONCAT('{"id":', `id`, ',"name":"', `name`, '"}') AS user_json FROM users LIMIT 1;
-- 返回子串首次出現位置 (1-based),不存在返回 0
SELECT LOCATE('hello', 'hello world'); -- 1
SELECT LOCATE('world', 'hello world'); -- 7
SELECT LOCATE('mysql', 'hello world'); -- 0
-- 應用:篩選包含關鍵詞的文章
SELECT * FROM articles WHERE LOCATE('MySQL', `content`) > 0;
-- 注意:不走索引,大表需全文索引
-- 基礎:每城市用戶數
SELECT `city`, COUNT(*) AS user_count
FROM `customers`
GROUP BY `city`;
-- 進階:多維聚合
SELECT
`city`,
COUNT(*) AS total,
AVG(`age`) AS avg_age,
MIN(`created_at`) AS first_user,
MAX(`balance`) AS max_balance
FROM `customers`
GROUP BY `city`
HAVING COUNT(*) > 100; -- 過濾聚合結果
GROUP BY 列必須出現在 SELECT 或聚合函數中 (ONLY_FULL_GROUP_BY 模式)HAVING 針對聚合後結果過濾,WHERE 針對原始行
-- 找出訂單金額超過 10000 的用戶
SELECT `user_id`, SUM(`amount`) AS total_amount
FROM `orders`
GROUP BY `user_id`
HAVING SUM(`amount`) > 10000;
-- 結合多條件
HAVING COUNT(*) > 10 AND AVG(`score`) >= 80
HAVING 可使用別名 (MySQL 擴展):HAVING total_amount > 10000WHERE 過濾行,再 GROUP BY,最後 HAVING 過濾組
SELECT select_list -- 5. 選擇輸出列
FROM table -- 1. 確定數據源
WHERE condition -- 2. 行級過濾
GROUP BY group_cols -- 3. 分組
HAVING group_condition -- 4. 組級過濾
ORDER BY order_cols -- 6. 排序
LIMIT offset, count; -- 7. 限制輸出
-- 單列去重
SELECT DISTINCT `city` FROM `customers` ORDER BY `id` DESC;
-- 多列去重 (組合唯一)
SELECT DISTINCT `city`, `province` FROM `customers`;
-- 計數去重
SELECT COUNT(DISTINCT `city`) FROM `customers`;
DISTINCT 作用於**所有 SELECT 列的組合**,非單列DISTINCT 需排序/哈希去重,消耗大,考慮近似算法 (HyperLogLog)
-- 前 10 條
SELECT * FROM articles LIMIT 10;
-- 第 3 頁 (每頁 10 條)
SELECT * FROM articles LIMIT 20, 10; -- 偏移 20,取 10
-- 或標準寫法
SELECT * FROM articles LIMIT 10 OFFSET 20;
-- 取第 100 條之後所有 (大偏移慎用)
SELECT * FROM articles LIMIT 100, 18446744073709551615; -- MAX ULLONG
-- 更好:游標分頁 WHERE id > last_id LIMIT 10
LIMIT 1000000, 10 需掃描棄取 100 萬行,**極慢**WHERE id > last_seen_id ORDER BY id LIMIT 10,利用索引定位,性能恆定
SELECT
u.`user_name`,
o.`order_no`,
o.`amount`
FROM `users` u
INNER JOIN `orders` o
ON u.`id` = o.`user_id` -- 關聯條件
WHERE o.`created_at` > '2023-01-01'
ORDER BY u.`id` DESC;
user_id) 必須有索引,否則 Hash Join / Block Nested Loop 慢
WITH `active_users` AS (
SELECT `id`, `name` FROM `users` WHERE `status` = 1
),
`recent_orders` AS (
SELECT `user_id`, `order_no`, `amount`
FROM `orders`
WHERE `created_at` > DATE_SUB(NOW(), INTERVAL 30 DAY)
)
SELECT
u.`name`,
o.`order_no`,
o.`amount`
FROM `active_users` u
JOIN `recent_orders` o ON u.`id` = o.`user_id`;
10 大 SELECT 技巧核心:**規範格式化、IN 批量查詢、CONCAT 字符串構造、LOCATE 文本搜索、GROUP BY/HAVING 聚合分析、理解執行順序、DISTINCT 去重、LIMIT 分頁優化 (游標分頁)、多表關聯別名索引、CTE 邏輯解耦**。熟練組合這些模式,能解決 90% 業務查詢場景,寫出可讀、高效、可維護的 SQL。