需求:優先查詢 users 表,找到即返回;未找到才查詢 users_archived。普通 UNION ALL 會掃描兩表,造成不必要開銷。
SELECT GREATEST(@found := -1, id) AS id, 'users' AS src_table
FROM users WHERE id = 1
UNION ALL
SELECT id, 'users_archived'
FROM users_archived WHERE id = 1 AND @found IS NULL
UNION ALL
SELECT 1, 'reset'
FROM DUAL WHERE (@found := NULL) IS NOT NULL;
@found := -1 賦值為 -1 (非 NULL),GREATEST(-1, id) 回傳 id,@found 變為 -1。WHERE ... AND @found IS NULL 因 @found=-1 不滿足,直接跳過,不掃描 users_archived。(@found := NULL) IS NOT NULL 永遠為 FALSE(賦值結果為 NULL),不產生資料,但完成 @found 重置為 NULL,供下次查詢使用。GREATEST / LEAST 可在 SELECT 列表中執行賦值並回傳業務值,避免額外欄位。@var 為會話級,連線斷開自動釋放,無汙染風險。DUAL 為虛擬表,配合 WHERE FALSE 達成「僅執行副作用」目的。CTE + UNION ALL + LIMIT 1,可讀性更高:WITH first_match AS (
SELECT id, 'users' AS src FROM users WHERE id = 1
UNION ALL
SELECT id, 'users_archived' FROM users_archived WHERE id = 1
)
SELECT * FROM first_match LIMIT 1;
若優先順序可配置,應用層拼接 SQL 或存儲過程動態構建上述 UNION 結構。