子查詢在 WHERE、HAVING 子句中的四大測試類型:**比較測試、集合成員測試 (IN)、存在性測試 (EXISTS)、限定比較測試 (ANY/ALL)**,配合銷售資料庫實例完整示範。
OFFICES:銷售據點SALESREPS:業務員ORDERS:訂單-- 列出銷售目標超過所有業務員定額總和的據點
SELECT CITY
FROM OFFICES
WHERE TARGET > (SELECT SUM(QUOTA) FROM SALESREPS WHERE REP_OFFICE = OFFICE);
-- 列出定額小於全公司目標 10% 的業務員
SELECT NAME
FROM SALESREPS
WHERE QUOTA < (0.1 * (SELECT SUM(TARGET) FROM OFFICES));
執行邏輯:外層逐列掃描,內層依外層當前列值計算標量,比較後決定保留。
-- 列出西部地區據點的業務員
SELECT NAME, AGE
FROM SALESREPS
WHERE REP_OFFICE IN (SELECT OFFICE FROM OFFICES WHERE REGION = 'Western');
-- 等效 JOIN 寫法
SELECT NAME, AGE
FROM SALESREPS, OFFICES
WHERE REP_OFFICE = OFFICE AND REGION = 'Western';
-- 找出有下單記錄的業務員
SELECT NAME FROM SALESREPS s
WHERE EXISTS (SELECT 1 FROM ORDERS o WHERE o.REP = s.EMPL_NUM);
-- 找出從未下單的業務員
SELECT NAME FROM SALESREPS s
WHERE NOT EXISTS (SELECT 1 FROM ORDERS o WHERE o.REP = s.EMPL_NUM);
EXISTS 優勢:不受 NULL 干擾、半連接優化 (找到即停止)、大表效能優於 IN。
-- 定額超過平均定額的業務員
SELECT NAME, AGE
FROM SALESREPS
WHERE QUOTA > (SELECT AVG(QUOTA) FROM SALESREPS);
-- 等效 ANY (此處等價)
WHERE QUOTA > ANY (SELECT QUOTA FROM SALESREPS); -- 不同語意,僅示範語法
針對**群組**進行篩選。
SELECT NAME, AVG(AMOUNT)
FROM SALESREPS, ORDERS
WHERE EMPL_NUM = REP AND MFR = 'ACI'
GROUP BY NAME
HAVING AVG(AMOUNT) > (SELECT AVG(AMOUNT) FROM ORDERS);
SELECT NAME, AVG(AMOUNT)
FROM SALESREPS, ORDERS
WHERE EMPL_NUM = REP AND MFR = 'ACI'
GROUP BY NAME, EMPL_NUM
HAVING AVG(AMOUNT) >= (SELECT AVG(AMOUNT) FROM ORDERS WHERE REP = EMPL_NUM);