简体   繁体   English

Rails:要么没有关联记录,要么没有由特定条件创建的关联记录

[英]Rails: Either no associated records OR none of the associated records created by aspecific condition

class User
   has_many :contacts
end

class Contact
   belongs_to :user
   # id
   # contact_type -> ['main', 'work', 'home']
end

What is the cleanest way to get only those users that either don't have any contact OR if they have contacts then none of the contact_type value is main ?什么是只获取那些没有任何联系人或如果他们有联系人的用户的最干净的方法,那么contact_type值都不是main

Example:例子:

User: id: 1, name: 'Dev'
Contacts: []

User: id: 2, name: 'Mike'
Contacts: [
  id: 1, contact_type: 'work'
  id: 2, contact_type: 'main'
]

User: id: 3, name: 'John'
Contacts: [
  id: 3, contact_type: 'work'
  id: 4, contact_type: 'home'
]

Result: Should return users with id 1 and 3结果:应该返回 id 为 1 和 3 的用户

You can left join users and contacts , group the rows by the users.id column, filter the groups without main contacts (using count with a case statement), and select the columns from the users table.您可以左连接userscontacts ,按users.id列对行进行分组,过滤没有主要联系人的组(使用带有case语句的count ),以及 select 来自users表的列。

If you're using Rails 5+, you can use left_outer_joins .如果您使用的是 Rails 5+,则可以使用left_outer_joins

User
  .left_outer_joins(:contacts)
  .group('users.id')
  .having("count(case when contact_type = 'main' then 1 end) = 0")

On older versions, you can pass a SQL fragment to the joins method to perform a left join.在旧版本上,您可以将 SQL 片段传递给joins方法以执行左连接。

 User
   .joins('left join contacts on contacts.user_id = users.id')
   .group('users.id')
   .having("count(case when contact_type = 'main' then 1 end) = 0")

SQL fiddle SQL 小提琴

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

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