2012-05-14 36 views
0

我有3個表格 - 帖子,友誼和喜歡 - 下面描述的重要字段。試圖寫一個查詢來選擇由我,我的朋友或我的朋友寫的帖子選擇的帖子

帖子:id, user_id, title

友誼:requester_id, accepter_id, is_confirmed

喜歡:post_id, user_id

我有(),它應該返回崗位,要麼我寫的,我確認的朋友寫了一個方法調用的get_relevant_posts,或我確認的朋友喜歡。我已經在SQLAlchemy中實現了這個功能,但是我的查詢中存在一個錯誤,因爲它只在友誼表不是空的時才起作用(無論它裏面的內容是什麼,只是不能爲空)。如果它是空的,什麼都不會返回(不正確的加入?)。

這不是一個大問題,因爲友誼表會在99.99%的時間內擁有一些東西。但我仍然希望退後一步,用簡單的SQL來寫這篇文章 - 我似乎無法把它包裹起來。

SQLAlchemy的CODE

Friendship1 = aliased(Friendship) 
Friendship2 = aliased(Friendship) 
Friendship3 = aliased(Friendship) 
Friendship4 = aliased(Friendship) 
return (DBSession.query(Post) 
     .outerjoin(Friendship1, Post.user_id==Friendship1.accepter_id) 
     .outerjoin(Friendship2, Post.user_id==Friendship2.requester_id) 
     .outerjoin(Like, Post.id==Like.post_id) 
     .filter(or_(
      # My post 
      self.id==Post.user_id, 
      # My friends post, where I'm the requester of the friendship 
      and_(self.id==Friendship1.requester_id, 
       Friendship1.is_confirmed==True), 
      # My friends post, where I'm the accepter of the friendship 
      and_(self.id==Friendship2.accepter_id, 
       Friendship2.is_confirmed==True), 
      # Somebodies post, which my friends found interesting 
      and_(self.id==Friendship3.requester_id, 
       Friendship3.is_confirmed==True, 
       Like.user_id==Friendship3.accepter_id), 
      and_(self.id==Friendship4.accepter_id, 
       Friendship4.is_confirmed==True, 
       Like.user_id==Friendship4.requester_id))) 
     .order_by(Post.created_at.desc()) 
     .limit(limit) 
     .offset(offset) 
     .all()) 

生成此

SELECT posts.title AS posts_title 
FROM friendships AS friendships_1, friendships AS friendships_2, posts LEFT OUTER JOIN friendships AS friendships_3 ON posts.user_id = friendships_3.accepter_id LEFT OUTER JOIN friendships AS friendships_4 ON posts.user_id = friendships_4.requester_id LEFT OUTER JOIN likes ON posts.id = likes.post_id LEFT OUTER JOIN users AS users_1 ON users_1.id = posts.user_id 
WHERE (posts.user_id = %s OR friendships_3.requester_id = %s AND friendships_3.is_confirmed = %s OR friendships_4.accepter_id = %s AND friendships_4.is_confirmed = %s OR friendships_1.requester_id = %s AND friendships_1.is_confirmed = %s AND likes.user_id = friendships_1.accepter_id OR friendships_2.accepter_id = %s AND friendships_2.is_confirmed = %s AND likes.user_id = friendships_2.requester_id) ORDER BY posts.created_at DESC 
LIMIT %s 
+0

這聽起來像你想在友誼表上做一個外連接,但是你正在做一個內連接。 – Ilion

+0

向我們展示您的代碼,以便我們看看問題是什麼 – Lamak

+0

@llion我想到了很多。正如你所看到的,出於某種原因,所產生的代碼是從友誼表加入的。 – BDuelz

回答

0

假設我們有MS SQL 2005

With rels 
(
    Select f.requesterId as target_id 
    From friendships f 
    Where is_confirmed = 1 and f.accepter_id='Your Id' 
    Union 
    Select 'Your id' 
) 
Select p.* 
From posts p 
    left join rel r on r.target_id = p.user_id -- this will be null on for non-target users 
    left join likes l on p.post_id=l.post_id -- here we will pick likes 
    left join rel r1 on r1.target_id=l.user_id 
where coalesce(r1.target_id, r2.target_id) is not null -- telling sql to pick posts we are interested in 

或更換CTE相對與子查詢。

0

以不同的方式來計算出來。使用IN子句做子查詢來檢查是否有任何喜歡該帖子的用戶是我已確認的朋友列表的一部分。其他部分很直截了當(檢查是我寫的還是朋友寫的)。

相關問題