-- 表1:用戶資料
pre_common_member_profile (uid, gender, birthyear, birthmonth, birthday)
-- 表2:好友關係
pre_home_friend (uid, fuid) -- uid 的好友為 fuid
-- 表3:好友請求
pre_home_friend_request (fuid, uid) -- fuid 請求加 uid 為好友
需求:查詢 uid=570 的用戶資料,排除其好友 (pre_home_friend.fuid) 和向其發送請求的用戶 (pre_home_friend_request.uid where fuid=570)。
SELECT gender, uid, birthmonth, birthday, birthyear
FROM pre_common_member_profile AS p
WHERE p.uid <> 570
AND p.uid < 570
AND gender = 0
AND uid NOT IN (
SELECT fuid FROM pre_home_friend WHERE uid = 570
UNION
SELECT uid FROM pre_home_friend_request WHERE fuid = 570
)
ORDER BY uid DESC;
NOT EXISTS 或 LEFT JOIN ... IS NULL。UNION 隱含 DISTINCT,若確定兩表無重疊或允許重複,用 UNION ALL 避免排序去重。
SELECT p.gender, p.uid, p.birthmonth, p.birthday, p.birthyear
FROM pre_common_member_profile p
LEFT JOIN (
SELECT fuid AS exclude_uid FROM pre_home_friend WHERE uid = 570
UNION ALL
SELECT uid AS exclude_uid FROM pre_home_friend_request WHERE fuid = 570
) excl ON p.uid = excl.exclude_uid
WHERE p.uid <> 570
AND p.uid < 570
AND p.gender = 0
AND excl.exclude_uid IS NULL
ORDER BY p.uid DESC;
-- 表2:好友查詢
CREATE INDEX idx_friend_uid ON pre_home_friend(uid);
-- 表3:請求查詢
CREATE INDEX idx_request_fuid ON pre_home_friend_request(fuid);
-- 表1:篩選條件
CREATE INDEX idx_profile_gender_uid ON pre_common_member_profile(gender, uid);
type 列為 ref 或 eq_ref(使用索引)。Extra 無 Using temporary、Using filesort(或可接受)。rows 估算值較小。WHERE uid NOT IN (...),避免大表子查詢。SDIFF 排除。uid 哈希分表,減少單表掃描量。通過 LEFT JOIN ... IS NULL 替代 NOT IN,配合 UNION ALL 和針對性索引,可顯著提升三表排除查詢性能。