Stress_test(id INT, key CHAR(2))id 非叢集索引;key 叢集索引id 有限重複;key 大量重複RAND() 產生隨機組合)找出同時滿足 key='Az'、key='Bw'、key='Cv' 三個條件的 id (即三個 key 值的交集)。
SELECT a.id FROM
(SELECT DISTINCT id FROM stress_test WHERE key = 'Az') a,
(SELECT DISTINCT id FROM stress_test WHERE key = 'Bw') b,
(SELECT DISTINCT id FROM stress_test WHERE key = 'Cv') c
WHERE a.id = b.id AND a.id = c.id
SELECT id FROM stress_test
WHERE key='Az' OR key='Bw' OR key='Cv'
GROUP BY id HAVING COUNT(DISTINCT key) = 3
SELECT DISTINCT id FROM stress_test A
WHERE NOT EXISTS (
SELECT 1 FROM
(SELECT 'Az' AS k UNION ALL SELECT 'Bw' UNION ALL SELECT 'Cv') B
LEFT JOIN stress_test C ON C.key = B.k AND C.id = A.id
WHERE C.id IS NULL
)
SELECT id FROM stress_test WHERE key = 'Az'
INTERSECT
SELECT id FROM stress_test WHERE key = 'Bw'
INTERSECT
SELECT id FROM stress_test WHERE key = 'Cv'
SELECT DISTINCT a.id FROM stress_test a, stress_test b, stress_test c
WHERE a.key='Az' AND b.key='Bw' AND c.key='Cv'
AND a.id=b.id AND a.id=c.id
| 排名 | 寫法 | 耗時 | 執行計畫特徵 |
|---|---|---|---|
| 1 | 寫法 2 (GROUP BY HAVING) | 最快 | 單次掃描叢集索引 + Hash Match Aggregate |
| 2 | 寫法 1 (子查詢 JOIN) | 次之 | 三次 Index Seek + Merge Join |
| 3 | 寫法 5 (自我 JOIN) | 較慢 | 三次 Index Seek + 兩次 Nested Loops |
| 4 | 寫法 3 (NOT EXISTS) | 慢 | 相關子查詢 + Left Outer Join,重複存取 |
COUNT(DISTINCT key) 準確語意表達「三個 key 皆存在」INTERSECT / EXISTS 往往因排序/相關子查詢開銷大而較慢key 設為叢集索引正確支援範圍/等值掃描;id 非叢集索引支援聯結-- 參數化版本,避免硬編碼
DECLARE @k1 CHAR(2)='Az', @k2 CHAR(2)='Bw', @k3 CHAR(2)='Cv';
SELECT id FROM stress_test
WHERE key IN (@k1, @k2, @k3)
GROUP BY id HAVING COUNT(DISTINCT key) = 3;