简体   繁体   English

ActiveRecord 限制从 company_ids 集合返回的用户

[英]ActiveRecord limit users returned from a collection of company_ids

I have an array of company_ids我有一组 company_ids
In the User model, I would like to find_by company_ids, but for each company_id, the user list returned should not exceed 5 users.User模型中,我想find_by company_ids,但是对于每个company_id,返回的用户列表不应超过5个用户。 How can I do that.我怎样才能做到这一点。

I have tried doing this我试过这样做

User.where(company_id: [1, 2, 3]).group('users.company_id').having('count(company_id) <= 5')

But this will return only those set where users in a company are not more than 5. Moreover, this wont return all the records.但这只会返回公司中用户不超过 5 的集合。此外,这不会返回所有记录。

What I am trying to do is, for company_ids = [1, 2, 3] , the collection should be able to return at max 5 users for company_id 1, then company_id 2, then company_id 3, and not load all the users for all those company_ids.我想要做的是,对于company_ids = [1, 2, 3] ,集合应该能够返回最多 5 个用户的 company_id 1,然后 company_id 2,然后 company_id 3,而不是加载所有用户那些 company_ids。

I think the further you can due to your MySQL version is just using UNION ALL .我认为由于您的 MySQL 版本,您可以进一步使用UNION ALL

You can create a query selecting the users by their company_id and then applying the LIMIT :您可以创建一个查询,通过他们的company_id选择用户,然后应用LIMIT

(select * from users where company_id = 1 LIMIT 2)
UNION ALL
(select * from users where company_id = 2 LIMIT 2)
UNION ALL
(select * from users where company_id = 3 LIMIT 2)

As Rails doesn't have a built-in support for UNION queries, you can create your own statement:由于 Rails 没有对UNION查询的内置支持,您可以创建自己的语句:

sql = [1, 2, 3].map { |id| "(SELECT * FROM users WHERE company_id = #{id} LIMIT 2)" }
               .join(" UNION ALL ")
User.find_by_sql(sql)

Update using MySQL8+使用 MySQL8+ 更新

SELECT id, name, company_id
FROM (
  SELECT id, name, company_id, ROW_NUMBER() OVER w AS company_user
  FROM users
  WINDOW w AS (PARTITION BY company_id)
) users
WHERE company_user <= 2;

The ActiveRecord way would be: ActiveRecord 的方式是:

User
  .select(:id, :name, :company_id)
  .from(
    User.select(:id, :name, :company_id, 'ROW_NUMBER() OVER w AS company_user')
        .from('users WINDOW w AS (PARTITION BY company_id)')
  )
  .where('company_user <= 2')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM