2012-06-02 23 views
2

我有這樣3個表:檢索用戶的朋友具有各好友只有一排柱

POST (id, name, id_user, ..) 
FRIENDS (id, followerid, followingid, acepted) /* acepted must be 1 to users be considered friends */ 

OK,所以我想從用戶5.讓所有朋友的帖子,但我有很多的麻煩構建查詢。我知道我需要加入,問題是當前用戶(ID爲5)可能是followerid或以下,所以我怎麼知道?

我試圖像成才(但得到被堵塞,nonsenseness):

SELECT posts.*,friends.id 
        FROM friends LEFT JOIN ON (friends.followerid = posts.id) OR (friends.following.id = posts.id) 

但我真的不知道,如果對接受或裏面,我可以在這裏得到一些暗示?謝謝!

+0

可以在同一對用戶添加兩次'FRIENDS'(爲'A,B'和'B, A')?如果是這樣,其中一行可以'acepted = 1',另一個'acepted = 0'?如果是這樣,應該把'B'作爲'A'的朋友(或者'A'作爲這個問題的'B'的朋友)? –

+0

每個連接只有一行。這就是爲什麼我決定添加接受的領域@AndriyM –

回答

1

一種ON子句類似於一個WHERE子句都接受(簡單或複雜)條件,這是一個布爾型表達式。 OR運營商是一個布爾運算符,因此它可以用於ON以及WHERE,所以隨時使用OR任何你喜歡的連接條件來建立一個滿足您的要求。

我認爲你基本上是在正確的軌道與您的查詢。我只想指出你可能錯過的一些事情,因爲你現在可能已經專注於其他事情了。

有一件事是加入的類型。我希望你的friends表應該包含各種用戶之間的所有現有鏈接,不僅包括用戶5和其他人之間的鏈接。因此,如果你加入friendsposts連接(這是一個外連接),你會得到所有的鏈接從friends,不僅用戶5的,這可能不是你想要的。當然,你可以添加一個WHERE子句,其條件如friends.id IS NOT NULL,但基本上相當於內部加入而沒有該條件。因此,請改用內部連接。

然而,有什麼可以需要爲您的WHERE條款friends.acepted = 1條件,當然,因爲你只想要用戶5的朋友參與,我以爲你的意思是那些證實成爲朋友,從而acepted應該是1

當然,對於用戶5也一定有條件。在我看來,如果你從friends得到只有用戶5的朋友,並且它們也是單列,那麼這將是最容易的。 (也就是說,兩個過濾器都將應用於派生表而不是連接的結果集。)這樣,將好友加入到posts表中會更容易,因爲您的連接條件會更簡單。這裏有一種方法,你怎麼會得出這樣一個表:

SELECT 
    id, 
    CASE followerid WHEN 5 THEN followingid ELSE followerid END AS friend_id 
FROM friends 
WHERE acepted = 1 
    AND (followerid = 5 OR followingid = 5) 

也就是說,這個查詢檢索是用戶5followerid = 5 OR followingid = 5)的朋友(acepted = 1)用戶ID。單用戶ID列friend_idfolloweridfollowingid組成:如果一個是5,則另一個被拉,反之亦然。

這就是你怎麼會在最終的查詢使用派生表:

SELECT 
    p.*, 
    f.id /* there's an `id` column in `posts`, so it might be a good idea 
      to assign `friends.id` a distinct alias, like `friends_id` */ 
FROM (
    SELECT 
    id, 
    CASE followerid WHEN 5 THEN followingid ELSE followerid END AS friend_id 
    FROM friends 
    WHERE acepted = 1 
    AND (followerid = 5 OR followingid = 5) 
) AS f 
    INNER JOIN posts AS p ON p.id_user = f.friend_id 
+0

感謝您提出的非常詳盡的答案,將盡力讓您知道 –

+0

'on子句'中的未知列'p.user_id'有什麼想法嗎? –

+0

應該是'p.id_user',我只是搞砸了列名,抱歉。 –

1

一種方式來做到這一點是與工會

SELECT posts.*,friends.id FROM friends LEFT JOIN posts ON 
(friends.followerid = posts.id) where friends.acepted = 1 and posts.id_user = 5 
UNION 
SELECT posts.*,friends.id FROM friends LEFT JOIN posts ON 
(friends.following.id = posts.id) where friends.acepted = 1 and posts.id_user = 5 
+0

所以和爲acepted = 1進入每個選擇與哪裏? –

+1

@Toni - 在我的例子中,是的 - 這兩個條款,你選擇的用戶ID將與每個選擇一起去。 – Gerrat

+0

我跳過此錯誤:您的SQL語法中有錯誤;檢查與您的MySQL服務器版本相對應的手冊,以便在'ON(friends.followerid = posts.id)where friends.acepted = 1和'在第2行 –

0

您的查詢應該工作:

SELECT posts.*, friends.id 
FROM friends LEFT JOIN 
    posts 
    ON (friends.followerid = posts.id) OR 
     (friends.following.id = posts.id) 

然而, 「或」 S 「亮起」 語句通常是低效率的。例如,他們肆意使用索引。請注意,當有追隨者和追隨者時,此方法將爲每個帖子生成多行。

另一種製劑是把兩者在同一行上:

SELECT posts.*, follower.id, following.id 
FROM posts left outer join 
    friends follower 
    ON follower.followerid = posts.id left outer join 
    friends following 
    on following.followingid = posts.id 
where follower.id = 5 or following.id = 5 
+0

這個還是聯盟更快?感謝您的回覆 –

+0

您的查詢沒有返回任何結果 –

相關問題