简体   繁体   English

Rails的Active Record中的SQL查询等效项

[英]Sql query equivalent in Rails' Active Record

Rails noob here...I'm trying to find the best option in my rails project. Rails新手...我正在尝试在Rails项目中找到最佳选择。 I have a sql query like this: 我有一个这样的SQL查询:

select sum(count) from (select count(user_id) as 'count' from accounts group by user_id having count(user_id) > 2) as A

All its trying to do is get the sum of count of users that have more than 2 accounts. 它所有要做的就是获得拥有两个以上帐户的用户总数。 While this sql query works fine by itself, I'm trying to find a way to translate this to Active Record. 虽然此sql查询本身可以正常工作,但我正在尝试找到一种将其转换为Active Record的方法。 Users and Accounts are rails models in my project. UsersAccounts是我项目中的Rails模型。

I'm assuming User has a has_many relationship with Accounts? 我假设用户与帐户具有has_many关系? In that case, you can do something like 在这种情况下,您可以执行以下操作

 User.find(id).accounts.count  

and each time a user with a particular id has >= 2 accounts, you can add 1 to the total count. 并且每次具有特定ID的用户拥有> = 2个帐户时,您都可以在总数中加1。

Or you could do something like 或者你可以做类似的事情

count = 0
@users = User.all 
@users.each do |user|
   if user.accounts.count >= 2
     count += 1
   end
end

Hopefully this is something you were looking for. 希望这是您正在寻找的东西。

timmy's solution should work, but will cause N+1 queries . timmy的解决方案应该可以工作,但是会导致N + 1个查询 You can use .includes to eager load what you need in order to minimize queries to the database (I too assume you have set up your has_many and belongs_to association between users and accounts). 您可以使用.includes来加载需要的内容,以最大程度地减少对数据库的查询(我也假设您已经设置了用户和帐户之间的has_many和belongs_to关联)。 I believe this would be the optimized implementation: 我相信这将是优化的实现:

users = User.includes(:accounts)
count = 0

users.each do |user|
  count += 1 if user.accounts.count > 2
end

I believe you could even refactor this further by chaining on a .where, but I am not quite sure how. 我相信您甚至可以通过在.where上链接来进一步重构它,但是我不确定如何。 check the documentation page I linked to at the top. 检查我链接到顶部的文档页面。

Hope that helps. 希望能有所帮助。

As per the sql query provided by you, Account model (accounts table) has a column named user_id which you are using for grouping. 根据您提供的sql查询, Account model (accounts table)有一个名为user_id的列,您将使用该列进行分组。 First step is to group by user_id and find user wise account counts. 第一步是按user_id分组并查找用户明智的帐户计数。 This will create a hash looking like { u1: n_acc1, u2: n_acc2 } . 这将创建一个类似于{ u1: n_acc1, u2: n_acc2 }的哈希。 The select statement selects all (key: value) user_id: n_accounts pairs where n_accounts > 2 . select语句选择所有(key: value) user_id: n_accounts对,其中n_accounts > 2 Then you just need to map (value) n_accounts into an array and apply sum on it. 然后,您只需要将map (value) n_accounts到一个数组中并对其apply sum

Account.group(:user_id).count
       .select{ |user_id, n_accounts| n_accounts > 2 }
       .map{ |user_id, n_accounts| n_accounts }
       .sum

No need to use association and/or eager loading . 无需使用association and/or eager loading Should be faster than the other solutions. 应该比其他解决方案更快。 Also, issues a single db query to find grouped count, rest all calculations would be on ruby side. 另外,发出单个数据库查询以查找分组计数,其余所有计算将在红宝石方面进行。

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

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