我有这 3 个表:
POST (id, name, id_user, ..)
FRIENDS (id, followerid, followingid, acepted) /* acepted must be 1 to users be considered friends */
好的,所以我想从用户 5 那里获取所有朋友的帖子。 但是我在构建查询时遇到了很多麻烦。 我知道我需要加入,问题是当前用户(ID 为 5)可能是关注者或关注 ID,所以我怎么知道?
我正在尝试类似的东西(但被废话阻止了):
SELECT posts.*,friends.id
FROM friends LEFT JOIN ON (friends.followerid = posts.id) OR (friends.following.id = posts.id)
但我真的不知道ON是否接受OR内部,我可以在这里得到一些提示吗? 谢谢!
ON
子句类似于WHERE
子句,因为它们都接受(简单或复杂)条件,这是一个布尔表达式。OR
运算符是一个布尔运算符,因此它可以在ON
和WHERE
中使用,因此请随意OR
连接条件中以任何您喜欢的方式使用,以构建满足您要求的一种。
我认为您的查询基本上走在正确的轨道上。我只想指出一些你可能错过的东西,仅仅是因为你现在可能专注于其他事情。
一件事是联接的类型。我希望您的friends
表应该包含不同用户之间的所有现有链接,而不仅仅是用户5
与其他任何人之间的链接。因此,如果您使用左联接(这是外联接)friends
连接到posts
,您将从friends
获得所有链接,而不仅仅是用户5
,这可能不是您想要的。当然,您可以添加带有 friends.id IS NOT NULL
等条件的 WHERE
子句,但这实质上等同于没有该条件的内部连接。因此,请改用内部联接。
但是,您的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)
也就是说,此查询检索作为用户5
(followerid = 5 OR followingid = 5
) 的好友 ( acepted = 1
) 的用户 ID。单用户 ID 列 friend_id
由 followerid
或 followingid
组成:如果一个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
一种方法是使用联合
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
您的查询应该有效:
SELECT posts.*, friends.id
FROM friends LEFT JOIN
posts
ON (friends.followerid = posts.id) OR
(friends.following.id = posts.id)
但是,"on"语句中的"or"通常效率低下。 例如,它们对索引的使用造成了严重破坏。 请注意,当有关注者和关注者时,此方法将为每个帖子生成多行。
另一种表述是将两者放在同一行上:
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