Rails5中按已读书籍数量排序用户(含未读书用户)
解决方案
要实现包含所有用户并按已读书籍数量排序(未读书用户排最后),核心是把内连接换成左外连接,同时正确统计符合条件的书籍数量:
方法一:使用SUM统计已读书籍数
users = User.left_outer_joins(:books) .select('users.*, SUM(CASE WHEN books.read = 1 THEN 1 ELSE 0 END) AS count_read_books') .group('users.id') .order('count_read_books DESC')
代码说明:
left_outer_joins(:books):左外连接会保留所有用户记录,哪怕该用户没有关联书籍SUM(CASE WHEN books.read = 1 THEN 1 ELSE 0 END):仅统计read=1的书籍数量,无符合条件书籍时结果为0group('users.id'):按用户ID分组,确保每个用户只返回一条记录order('count_read_books DESC'):按已读书籍数降序排列,数量为0的用户会自动排在最后
方法二:使用COUNT统计(更严谨处理边界场景)
如果担心部分场景下统计结果为NULL,可以用COUNT结合CASE WHEN:
users = User.left_outer_joins(:books) .select('users.*, COUNT(CASE WHEN books.read = 1 THEN 1 END) AS count_read_books') .group('users.id') .order('CASE WHEN count_read_books = 0 THEN 1 ELSE 0 END, count_read_books DESC')
代码说明:
COUNT(CASE WHEN books.read = 1 THEN 1 END):仅对read=1的书籍计数,无符合条件时结果为0- 排序时先通过
CASE WHEN将未读书用户(count=0)标记为1,其他标记为0,确保这类用户排在最后,再按计数降序排列
原代码问题分析
你用的joins(:books)是Rails默认的内连接,只有当用户存在关联书籍时才会被保留,所以未读书籍的用户被过滤掉了。换成左外连接就能解决这个问题。
内容的提问来源于stack exchange,提问作者sara lance
相关产品推荐
相关产品推荐

