ActiveRecord多状态独立限制查询:如何获取各状态最新10条数据
解决Rails中按状态分别取最新N条数据的问题
这个坑我之前踩过!你用or方法组合两个带limit的查询时,Rails会把两个查询的条件合并到同一个WHERE子句里,然后把limit提升到整个查询的外层,所以最终还是只返回10条数据,根本达不到每种状态各取10条的效果。
要实现需求,得用UNION来拼接两个独立的查询结果,这样每个子查询的limit会各自生效,最后合并成20条数据。具体代码如下:
# 先分别查询每种状态的最新10条数据(记得按创建时间倒序,确保拿到最新的) active_users = User.where(status: :active).order(created_at: :desc).limit(10) declined_users = User.where(status: :declined).order(created_at: :desc).limit(10) # 用UNION ALL合并两个查询结果(如果不会有重复数据,UNION ALL比UNION更高效) combined_users = User.from("(#{active_users.to_sql} UNION ALL #{declined_users.to_sql}) AS users")
补充说明:
- 如果你的业务场景中存在同一个用户可能同时出现在两个状态查询中的情况(虽然理论上用户状态应该是唯一的),可以把
UNION ALL换成UNION,它会自动去重,但性能会稍差一点。 - 如果需要把合并后的20条数据再统一排序(比如按创建时间倒序),可以在最后追加
order方法:combined_users = User.from("(#{active_users.to_sql} UNION ALL #{declined_users.to_sql}) AS users").order(created_at: :desc)
为什么之前的or方法不行?因为Rails的or对两个查询有结构一致性要求,当你合并两个带limit的查询时,它会忽略子查询的limit,只保留外层的一个limit,所以生成的SQL就是你看到的那样,自然满足不了需求。
内容的提问来源于stack exchange,提问作者Nicos Karalis
相关产品推荐
相关产品推荐

