Rails Active Record连接查询与排序和限制

时间:2017-12-18 11:53:50

标签: ruby-on-rails ruby activerecord left-join inner-join

我正在努力整理一个相当复杂的Active Record查询,而且我对Rails还是个新手。

关系

以下是查询的相关模型关系:

  • 团队可以包含多个用户
  • 用户可以使用 team_id 列来跟踪他们所在的团队。
  • 团队有一个管理员,这是一个用户。这是在团队的 admin_id 列中。
  • 用户有一个电子邮件地址(例如foo@example.com)。

模式

以下是schema.rb的相关部分:

create_table "teams", force: :cascade do |t|
  t.integer "admin_id"
end

create_table "users", force: :cascade do |t|
  t.string "email", default: "", null: false
  t.integer "team_id"
end

add_foreign_key "teams", "users", column: "admin_id"
add_foreign_key "users", "teams"

查询

鉴于域名(例如example.com),我希望找到拥有该域名电子邮件地址的管理员的团队。如果有多个匹配,我想只有拥有最多用户的团队。这是我到目前为止所做的:

team = Team.joins('INNER JOIN users ON admin_id = users.id')
           .where('email LIKE ?', "%example.com")
           .where(domain_sign_up: true)

问题

此查询的问题在于它将所有匹配作为数组返回。我想通过team.users.count订购,然后只返回第一个(用户最多)团队作为对象,而不是数组。这可能是LEFT OUTER JOIN的候选人吗?

谢谢!

2 个答案:

答案 0 :(得分:5)

尝试这样的事情

team = Team.joins('INNER JOIN users ON admin_id = users.id')
           .where('email LIKE ?', "%example.com")
           .where(domain_sign_up: true)
           .group('teams.id')
           .select('teams.*, COUNT(users.id) AS team_users_count')
           .order('COUNT(users.id) DESC')
           .first

我将limit(1)更改为first。如果参数为1,则似乎没有多大意义limit,因此您有一个Team,而不是一个团队的关系。

答案 1 :(得分:0)

Ursus发布的答案非常有用,但我最后在团队中添加了一个名为“域”的新列,以简化操作,然后使用.left_join按用户排序。这是我的最终查询:

team = Team.left_joins(:users)
           .where(domain: 'example.com', domain_sign_up: true)
           .group('teams.id')
           .order('COUNT(users.id) DESC')
           .first