本文整理自《SQL 必知必會》前 13 章的學習筆記,涵蓋 SQL 基礎語法、過濾、排序、通配符、計算欄位、函數、聚合、分組、子查詢、聯結等核心知識點,所有範例均在 MySQL 環境下實測。
-- 指定欄位查詢並按主鍵排序
SELECT prod_id, prod_name, prod_desc
FROM products
ORDER BY prod_id;
-- 多欄位排序:先按價格升序,再按名稱升序
SELECT prod_id, prod_name, prod_desc
FROM products
ORDER BY prod_price, prod_name;
-- 混合排序:價格升序,名稱降序
SELECT prod_id, prod_name, prod_desc
FROM products
ORDER BY prod_price, prod_name DESC;
-- 空值判斷
SELECT prod_id, prod_name FROM products WHERE prod_price IS NULL;
-- 複雜條件組合:AND/OR 優先級與括號
SELECT prod_id, prod_name, prod_desc
FROM products
WHERE (vend_id <> 'DLL01' OR prod_id LIKE 'BR%')
AND prod_price BETWEEN 3 AND 10;
-- IN 操作符:簡化多個 OR 條件
SELECT prod_id, prod_name, prod_desc
FROM products
WHERE vend_id IN ('DLL01','BRS01')
ORDER BY prod_name;
-- NOT IN:排除特定值
SELECT prod_id, prod_name, prod_desc
FROM products
WHERE vend_id NOT IN ('DLL01','BRS01')
ORDER BY prod_name;
%:匹配任意字元(零個或多個)_:匹配單個字元[]:字元集合(MySQL 不支援,需用 REGEXP 替代)-- 以 'Fish' 開頭,或名稱符合 '__ inch teddy bear' 模式
SELECT prod_id, prod_name, prod_desc
FROM products
WHERE prod_name LIKE '__ inch teddy bear' OR prod_name LIKE 'Fish%';
最佳實踐: 避免過度使用通配符;不要將通配符置於搜尋模式開頭(如 %keyword),會導致全表掃描,效能極差。
MySQL 使用 CONCAT() 而非 + 或 ||(後兩者在 MySQL 中為算術加法或邏輯 OR,結果為 0)。
-- 正確拼接
SELECT CONCAT(vend_name, '(', vend_country, ')') AS vend_title
FROM vendors ORDER BY vend_name;
-- 算術運算建立計算欄位
SELECT prod_id, quantity, item_price,
quantity * item_price AS expanded_price
FROM orderitems
WHERE order_num = 20008;
-- 日期/時間函數
SELECT CONCAT(prod_name, '+', CURDATE()) FROM products;
SELECT order_num FROM orders WHERE YEAR(order_date) = 2004;
-- 字串函數
SELECT UPPER(prod_name) AS prod_name_upper, prod_price
FROM products ORDER BY prod_name;
-- 去除空白
SELECT TRIM(' test '); -- 返回 'test'
注意: 函數在不同 DBMS 中語法差異大,移植性較差,使用時務必加註釋說明適用資料庫。
-- 基本聚合
SELECT AVG(prod_price) AS avg_price FROM products;
SELECT COUNT(*) AS num_cust FROM customers;
-- 進階:DISTINCT 去重統計
SELECT COUNT(*) AS items,
AVG(DISTINCT prod_price) AS avg_distinct_price,
MAX(prod_price) AS max_price,
MIN(prod_price) AS min_price
FROM products;
執行順序:SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY
-- 按供應商分組統計商品數
SELECT vend_id, COUNT(*) AS num_prods
FROM products
GROUP BY vend_id;
-- 按價格分組,並過濾數量 >= 2 的組
SELECT prod_price, COUNT(*) AS num_price
FROM products
GROUP BY prod_price
HAVING COUNT(*) >= 2
ORDER BY prod_price DESC;
關鍵點: WHERE 過濾行,HAVING 過濾分組;SELECT 清單中的非聚合欄位必須出現在 GROUP BY 中。
原則:由內而外、由特殊到一般。
-- 找出購買特定商品 (RGAN01) 的客戶
SELECT cust_id
FROM orders
WHERE order_num IN (
SELECT order_num FROM orderitems WHERE prod_id = 'RGAN01'
);
相關子查詢(外部引用內部表別名):
SELECT cust_name, cust_state,
(SELECT COUNT(*) FROM orders WHERE orders.cust_id = customers.cust_id) AS orders
FROM customers
ORDER BY cust_name;
-- 內聯結 (INNER JOIN):僅返回匹配行
SELECT vend_name, prod_name, prod_price
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id;
-- 左外聯結 (LEFT JOIN):保留左表所有行
SELECT C.cust_id, O.order_num
FROM customers AS C LEFT OUTER JOIN orders AS O
ON C.cust_id = O.cust_id;
-- 右外聯結 (RIGHT JOIN):保留右表所有行
MySQL 不支援 FULL OUTER JOIN 與舊式 *= 語法,可用 UNION 模擬全外聯結。
-- 使用別名簡化多表查詢
SELECT P.prod_id, P.prod_name, SUM(O.quantity) AS total_qty
FROM products AS P LEFT OUTER JOIN orderitems AS O
ON P.prod_id = O.prod_id
GROUP BY P.prod_name
ORDER BY P.prod_id;
此查詢展示所有商品(含無銷售記錄者),並統計總銷量。