MYSQL:每个whereIn()限制行数

时间:2017-02-08 21:33:24

标签: mysql greatest-n-per-group where-in right-join sql-limit

用户表

ID

user_comments表

id | user_id |内容| created_at

我有一个用户ID列表,我想为每个用户ID获取最新的3条评论。

SELECT * FROM user_comments WHERE user_id IN (1, 2, 3, 4, 5) 
ORDER BY created_at DESC
LIMIT 3;

这将从所有匹配ID获取最后3条评论,我想要每个 ID的最后3条评论。 1个没有工会首选的查询。

我已经尝试过直接加入桌子,但我似乎无法做到正确。

** 编辑:我不能依赖id列进行排序,必须使用日期列。

感谢。

** 我的最终解决方案

SELECT user_comments.* FROM user_comments
LEFT OUTER JOIN user_comments user_comments_2
ON user_comments.post_id = user_comments_2.post_id 
    AND user_comments.id < user_comments_2.id    
where user_comments.post_id in (x,x,x) 
GROUP BY user_comments.id 
HAVING COUNT(*) < 3 
ORDER BY user_id, created_at

@PaulSpiegel提出的答案确实对我有用(但需要注意),但我最终使用上述联接解决方案,使用来自此主题的信息:link

比尔卡文提到了

谢谢大家!

2 个答案:

答案 0 :(得分:2)

如果您可以使用id代替created_at,则可以将id与每位用户的第3高id进行比较。您可以在LIMIT 1 OFFSET 2的子查询中找到该文件。对于用户少于3条评论的情况,请使用COALESCE(或IFNULL)选择id >= 0的所有评论。

SELECT * 
FROM user_comments c
WHERE user_id IN (1, 2, 3, 4, 5)
  AND id >= COALESCE((
    SELECT id
    FROM user_comments c1
    WHERE c1.user_id = c.user_id
    ORDER BY id DESC
    LIMIT 1
    OFFSET 2
), 0)
ORDER BY user_id, id DESC

如果您无法使用id进行订购..

SELECT * 
FROM user_comments c
WHERE user_id IN (1, 2, 3, 4, 5)
  AND created_at >= COALESCE((
    SELECT created_at
    FROM user_comments c1
    WHERE c1.user_id = c.user_id
    ORDER BY created_at DESC
    LIMIT 1
    OFFSET 2
), '1970-01-01 00:00:00')
ORDER BY user_id, created_at DESC

请注意,如果第3个和第4个评论具有相同的时间戳,那么您可能(但不太可能)获得超过3条评论。

答案 1 :(得分:1)

尝试

select * 
from (
    select *, 
        @currentRank := if(@prevId = user_id, @currentRank, 0) + 1 as rank, 
        @prevId := user_id
    from user_comments
    order by user_id, created_at desc) as user_comments 
where rank <= 3

内部查询使用 SQL @ variables 来更改行之间的值。由于order by user_id,特定用户的评论将被分组在一起。 @currentRank变量将在特定组中存储行级别。当新组开始时,@currentRank将被清零。

结果退出最优,因为它需要RDMS只对user_comments表的每个记录进行一次迭代。但是,外部where子句将在之后执行。