检索用户朋友的帖子,每个友谊只有一行

时间:2012-06-02 01:56:23

标签: mysql sql join

我有这3张桌子:

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

好的,所以我想从用户5那里得到所有朋友的帖子。但是我在构建查询时遇到了很多麻烦。我知道我需要JOIN,问题是当前用户(id为5)可能是followerid或者followid,所以我怎么知道呢?

我正在尝试某种方式(但被无意义所阻止):

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

但我真的不知道ON是否接受OR内部,我可以在这里得到一些提示吗?谢谢!

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

ON子句类似于WHERE子句,它接受(简单或复杂)条件,这是布尔表达。 OR运算符是布尔运算符,因此它可以在ONWHERE中一起使用,因此可以随意使用OR在连接条件中你喜欢的任何方式来构建一个满足你要求的方式。

我认为您的查询基本上正确。我只想指出一些你可能会遗漏的事情,因为你现在可能只是集中在其他事情上。

有一点是联接的类型。我希望您的friends表应包含各个用户之间的所有现有链接,而不仅仅是用户5与其他任何用户之间的链接。因此,如果您使用加入(这是一个外部联接)加入friendsposts,您将获得所有来自{的所有链接{1}},不仅是用户friends,而且可能不是您想要的。当然,您可以添加一个5子句,其条件类似于WHERE,但这基本上等同于内部连接没有这个条件。因此,请改用内连接。

但是,您需要friends.id IS NOT NULL子句可能的是WHERE条件,当然,因为您只想让用户5的朋友参与,我认为您指那些确认成为朋友的人,因此friends.acepted = 1应为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) acepted = 1)的朋友(5)的用户ID。单个用户ID列followerid = 5 OR followingid = 5friend_idfollowerid组成:如果一个是followingid,则另一个被拉,反之亦然。

这就是你在最终查询中使用这个派生表的方法:

5

答案 2 :(得分:0)

您的查询应该有效:

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

但是,“on”语句中的“或”通常效率低下。例如,他们对索引的使用造成严重破坏。请注意,当有关注者和关注者时,此方法将为每个帖子生成多行。

另一种方法是将两者放在同一行:

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