你可以在你的 sqlfiddle 中试试这个。条件“WHERE user_id = 2”需要将 2 替换为您当前的用户 ID。
SELECT numbered.*
FROM
(SELECT ranked.*,
IF (post_id=@prev_post,
@n := @n + 1,
@n := 1 AND @prev_post := post_id) as position
FROM
(SELECT users_liked_posts.post_id,
users_liked_posts.user_id,
visitor.user_id as u1,
friendships.user_id as u2,
IF (visitor.user_id is not null, 1, IF(friendships.user_id is not null, 2, 3)) as rank
FROM users_liked_posts
INNER JOIN posts
ON posts.id = users_liked_posts.post_id
LEFT JOIN friendships
ON users_liked_posts.user_id = friendships.user_id
AND friendships.friend_id = posts.user_id
LEFT JOIN (SELECT post_id, user_id FROM users_liked_posts WHERE user_id = 2) visitor
ON users_liked_posts.post_id = visitor.post_id
AND users_liked_posts.user_id = visitor.user_id
ORDER BY users_liked_posts.post_id, rank) as ranked
JOIN
(SELECT @n := 0, @prev_post := 0) as setup) as numbered
WHERE numbered.position < 4
您可以轻松地将“编号”子查询与“用户”表连接起来,以获取更多用户信息。有额外的字段 u2, u3 可以帮助查看正在发生的事情。您可以删除这些。
查询的总体思路:
1) 两次左加入 users_liked_posts。第一次仅限于当前访问者,创建子查询访问者。第二次仅限于朋友。
2) 列rank, IF (visitor.user_id is not null, 1, IF(friendships.user_id is not null, 2, 3)),为users_liked_posts中的每个用户分配一个rank。此查询按帖子和排名排序。
3)使用前一个作为子查询来创建相同的数据,但每个帖子都有用户的运行位置。
4)使用previous作为子查询来提取每个帖子的前3个位置。
不,这些步骤不能合并,特别是因为 MySQL 不允许 WHERE 条件中的别名使用计算列。