投稿、友情、いいねの3つのテーブルがあります。以下に説明する重要なフィールドです。
投稿:id, user_id, title
友情:requester_id, accepter_id, is_confirmed
好きなもの:post_id, user_id
get_relevant_posts()というメソッドがあります。このメソッドは、自分が書いた、確認済みの友達が書いた、または確認済みの友達が気に入った投稿を返す必要があります。私はすでにこれをSQLAlchemyに実装しましたが、友情テーブルが空でない場合にのみ機能するため、クエリにバグがあります(何が含まれていても、空にすることはできません)。空の場合、何も返されません(不適切な結合?)。
友情テーブルには99.99%の確率で何かが含まれるため、これは大きな問題ではありません。しかし、それでも一歩下がって、これをプレーンSQLで記述したいと思います。頭を包み込むことができないようです。
SQLALCHEMYコード
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