2012-06-25 96 views
0

enter image description here選擇用戶不特定的用戶

您好的朋友,我有這兩個表:用戶和朋友(friend_status = 1表示發送請求,friend_status = 2意味着它們是朋友)。現在我想選擇所有用戶不是特定用戶的朋友。怎麼做?

假設當前用戶是1.我嘗試這樣的SQL。它可以工作,但它太長而且很慢。第一個選擇所有向user1發送請求但未被接受的用戶。第二個選擇所有用戶從user1接收請求。第三和第四個選擇所有用戶不在「朋友」表中。

SELECT user_id, name, email 
       FROM 
       (
        SELECT user_id, name, email 
        FROM users u INNER JOIN friends f ON u.user_id = f.sender 
        WHERE f.receiver = 1 AND friend_status <> 2 
        UNION 
        SELECT user_id, name, email 
        FROM users u INNER JOIN friends f ON u.user_id = f.receiver 
        WHERE f.sender = 1 AND friend_status <> 2 
      UNION 
      SELECT u.user_id, u.name, u.email 
        FROM users u LEFT JOIN friends f ON u.user_id = f.sender 
        WHERE f.receiver IS NULL 
        GROUP BY user_id 
       UNION 
      SELECT u.user_id, u.name, u.email 
        FROM users u LEFT JOIN friends f ON u.user_id = f.receiver 
        WHERE f.sender IS NULL 
        GROUP BY user_id 
       ) T 
     GROUP BY user_id 

更新:添加照片。 enter image description here

+0

請在http://www.sqlfiddle.com/上提供一些數據,以便我們測試並回答 –

+0

http://www.sqlfiddle.com/#!2/49302/1 – Emerald214

回答

1
SELECT 
    a.user_id, 
    a.name, 
    a.email, 
    b.status IS NOT NULL AS friend_status 
FROM 
    users a 
LEFT JOIN 
    friends b ON 
     a.user_id IN (b.sender, b.receiver) AND 
     1 IN (b.sender, b.receiver) 
WHERE 
    (b.friend_id IS NULL OR b.status <> 2) AND 
    a.user_id <> 1 

你問一個問題之前here - 「選擇誰不和任何人做朋友用戶」,我提供了利用的LEFT JOINanswer

大廈關閉的是,選擇誰不是朋友與特定用戶的用戶,我們只需要簡單地向特定用戶的ID添加到LEFT JOIN條件(1 IN (b.sender, b.receiver)。

輕微編輯:除非用戶可以親友,否則選擇反對的用戶也是沒有意義的!所以我加了WHERE a.user_id <> 1

+0

你再次,謝謝。這對我來說很複雜,所以我無法根據需要進行調整。 (是的,當然他不可能成爲朋友) – Emerald214

+0

嗨,還有一個問題,爲什麼你在JOIN子句中添加了多個條件,這對我來說很奇怪,因爲我被教導說條件應該在WHERE子句中。給我一些關於它的參考網站?到目前爲止,我只使用ON a.some_id = b.some_id,從不使用IN和JOIN。 – Emerald214

+0

它實際上非常靈活,您還想查詢什麼?希望從未發送過的用戶/從user_id'1'收到一個請求?只需刪除'b.status = 2' –

1

您可以通過使用像這樣簡化了這個:

SELECT user_id, name, email 
FROM 
(
    SELECT u.user_id, u.name, u.email 
    FROM users u LEFT JOIN friends f ON u.user_id = f.sender 
    WHERE IFNULL(friend_status,0) <> 2 
    GROUP BY user_id 
    UNION 
    SELECT u.user_id, u.name, u.email 
    FROM users u LEFT JOIN friends f ON u.user_id = f.receiver 
    WHERE IFNULL(friend_status,0) <> 2 
    GROUP BY user_id 
) T 
GROUP BY user_id 

IFNULL函數返回第一個參數的值,取值第二個參數的值替換NULL。在這種情況下,它意味着,如果在朋友表中,它允許你減少一半的UNION選擇的數量沒有匹配的朋友friend_status將被視爲0。

+0

#1582 - 錯誤的參數計數在調用本地函數「ISNULL」 – Emerald214

+0

我現在已經糾正了SQL。在MySQL正確的功能是IFNULL(我已經習慣了它使用ISNULL此SQL Server)。 – StevenR

+0

錯誤的結果輸出。 – Emerald214

1

假設你想在user_id 1執行查詢:

SELECT user_id, name, email 
FROM users AS u 
WHERE NOT EXISTS (SELECT * FROM friends AS f 
        WHERE (f.sender = u.user_id AND f.receiver = 1 AND f.friend_status = 2) 
        OR (f.sender = 1 AND f.receiver = u.user_id AND f.friend_status = 2) 
       ) 
AND u.user_id <> 1 

子查詢獲取所有建立的友好關係,其中用戶1或者是發送方或接收方。外部查詢選擇沒有這種關係的所有用戶。 ID爲1的用戶從查詢中使用的最後一行,因爲,即使他不能交朋友自己排除在外,我想他不應該出現在最終的查詢結果。

+0

它的工作原理,但我想在這個SELECT中獲得「friend_status」。 – Emerald214

+1

你對哪個「friend_status」感興趣?返回的用戶是發件人還是接收者的狀態?而且,如果朋友表中根本沒有這種關係呢? –

+0

行了吧....... – Emerald214

1

嘗試此查詢

select 
    u.user_id, 
    u.name, 
    u.email, 
    ifnull(f.friend_status,0) as Relation 
from users as u 
    left join friends as f 
    on f.sender = u.user_id 
where u.user_id not in(select 
      sender 
       from friends 
       where sender = 1) 

這裏發件人= 1表示的用戶ID = 1。可以通過用戶ID來限制此條件。另外狀態0意味着他不是朋友。與1,2,3,根據你的規則