2011-03-23 98 views
0

所以我有這個疑問:兩個連接語句

SELECT DISTINCT(b.friend_id) AS possible_id 
FROM friend_friends a 
    JOIN friends_friends b 
     ON b.user_id = a.friend_id 
WHERE a.user_id = 1703122278 

它將檢索朋友的朋友的特定用戶的

我有另一個數據庫,其中包含誰說他們不是朋友的人的數據。

下面是該查詢得到的名單說不是朋友:

SELECT friend_id 
FROM friends_not_friends 
WHERE user_id = 1703122278 
AND not_friends = 1 

然後我比較的不是朋友列表,從可能的朋友列表,從列表中刪除不是朋友。

如何組合這兩個查詢而不使用子查詢,而是使用連接?

+0

使用子查詢有什麼問題? – 2011-03-23 21:33:23

回答

3
SELECT DISTINCT(b.friend_id) AS possible_id 
FROM friend_friends a 
    JOIN friends_friends b 
    ON b.user_id = a.friend_id 
    LEFT JOIN friends_not_friends n 
    ON b.friend_id = n.friend_id 
     AND n.user_id = a.user_id 
     AND n.not_friends = 1 
WHERE a.user_id = 1703122278 
    AND n.friend_id IS NULL 

這顯示了

(1st list of friends of friends of 1703122278) 
MINUS 
(2nd list of not friends of 1703122278) 

我希望你不要」 t想要

list of friends of 
    (friends of 1703122278 
    minus 
    (2nd list of not friends of 1703122278) 
    ) 

只是在鬼混,這裏是查詢使用NOT IN。 我個人覺得這些更清晰,但是他們在速度方面可能效率較低。

-- Friends of friends of a user 
SELECT DISTINCT(b.friend_id) AS possible_id 
FROM friend_friends b      -- the b and a aliases 
WHERE b.user_id IN       -- can be removed 
    (SELECT a.friend_id 
    FROM friends_friends a 
    WHERE a.user_id = 1703122278 
) 
; 

和問了一句:

-- Friends of friends of a user that 
-- are also not not_friends of the user: 
SELECT DISTINCT(b.friend_id) AS possible_id 
FROM friend_friends b      -- the b, a and n aliases 
WHERE b.user_id IN       -- can be removed too 
    (SELECT a.friend_id 
    FROM friends_friends a 
    WHERE a.user_id = 1703122278 
) 
    AND b.friend_id NOT IN 
    (SELECT n.friend_id 
    FROM friends_not_friends n 
    WHERE n.user_id = 1703122278 
     AND n.not_friends = 1 
) 
; 
+0

這個人工作得很好。唯一的一點是我改變了n.user_id = 1703122278到n.user_id = a.user_id。簡化一點。謝謝! – ehftwelve 2011-03-23 22:02:53

+0

thnx。我也改變了我的答案。請檢查你是否想要查詢給出的內容,而不是像'朋友列表(朋友減去不友情)' – 2011-03-23 22:21:29

1

在oracle中我會使用MINUS運算符。

我THIK有在MySQL一個correlary功能 - 可能左連接或NOT IN子句

0

嘗試左外連接到friend_not_friends表(匹配上friend_id,過濾上USER_ID和not_friends標誌),然後消除那裏有一個匹配行的行從not_friends(即排除行,其中not_friend id爲NOT NULL)

SELECT DISTINCT(f.friend_id) AS possible_id 
    FROM friend_friends a 
    JOIN friends_friends f 
    ON f.user_id = a.friend_id 
    LEFT 
    JOIN friends_not_friends n 
    ON n.user_id = a.user_id 
    AND n.friend_id = f.friend_id 
    AND n.not_friends = 1 
WHERE a.user_id = 1703122278 
    AND n.user_id IS NULL 

訣竅是篩選出匹配的行,讓行未找到匹配的friends_not_friends表。這是查詢中的最後一個謂詞(n.user_id IS NULL),可以爲您進行篩選。


缺席的要求不使用子查詢,那麼像這樣的工作,以及:

SELECT DISTINCT(f.friend_id) AS possible_id 
    FROM friend_friends a 
    JOIN friends_friends f 
    ON f.user_id = a.friend_id 
    WHERE a.user_id = 1703122278 
    AND NOT EXISTS 
     (SELECT 1 
      FROM friends_not_friends n 
      WHERE n.friend_id = f.friend_id 
      AND n.user_id = a.user_id 
      AND n.not_friends = 1 
     ) 
1

這裏說過濾「不夠朋友」對兩個層面的解決方案(它過濾用戶的不可─的不-朋友用戶的朋友)的朋友:

SELECT 
    DISTINCT(b.friend_id) AS possible_id 
    FROM 
    friend_friends a 
    JOIN friend_friends b ON b.user_id = a.friend_id 
    LEFT JOIN friends_not_friends nfa 
     ON a.friend_id = nfa.user_id and nfa.not_friends = 1 
    LEFT JOIN friends_not_friends nfb 
     ON b.friend_id = nfb.user_id and nfb.not_friends = 1 
    WHERE 
    a.user_id = 1703122278 
    AND nfa.friend_id IS NULL 
    AND nfb.friend_id IS NULL 

的「絕招」是做一個LEFT JOIN並檢查是否有我沒有數據(NULL)。

順便說一句 - 有沒有一個理由,你不需要子選擇?有時LEFT JOIN - 更快,但子選擇往往是一個不錯的選擇。

+0

+1爲你最後的評論。我會補充說(第三種選擇)'NOT IN'解決方案通常是更清晰的代碼。 – 2011-03-23 22:27:07