2

我有这 3 张桌子:

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

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

我正在尝试类似的东西(但被胡说八道挡住了):

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

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

4

3 回答 3

1

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

我认为您的查询基本上走在正确的轨道上。我只想指出一些你可能错过的事情,仅仅是因为你现在可能专注于其他事情。

一件事是联接的类型。我希望您的friends表应该包含各个用户之间的所有现有链接,而不仅仅是用户5和其他任何人之间的链接。因此,如果您使用连接(即外连接)加入,您将获得friends来自的所有链接,而不仅仅是 user的,这可能不是您想要的。当然,您可以添加一个带有类似条件的子句,但这基本上等同于没有该条件的连接。因此,请改用内部联接。postsfriends5WHEREfriends.id IS NOT NULL

但是,您的WHERE子句可能需要friends.acepted = 1的当然是条件,因为您只希望用户 5 的朋友参与,我假设您的意思是那些被确认为朋友的人,因此acepted应该是1

当然,用户在5某个地方也必须有条件。在我看来,如果您从中派生一个表friends代表user 的朋友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的用户 ID 。单个用户 ID 列由或组成:如果一个是,则拉另一个,反之亦然。5followerid = 5 OR followingid = 5friend_idfolloweridfollowingid5

这就是您在最终查询中使用此派生表的方式:

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
于 2012-06-10T11:39:31.557 回答
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
于 2012-06-02T02:00:30.627 回答
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
于 2012-06-02T02:03:41.513 回答