2013-12-23 119 views
3

我试图让所有有医生相关的客户端,但他们都没有开始他们的第一次会议(一个客户has_many医生,可以有他们每个人的第一次会议)。Rails找到所有相关记录符合条件的地方

到目前为止,我有:

@clients = Client.joins(:doctors).where('doctors.first_session IS NULL').order('clients.id DESC') 

但是,当一个客户端,例如博士2人,这并不工作。第一个doctor.first_session = null,但第二个不是。这种情况将返回客户端,它不希望它。

任何想法?

回答

-2

你可以创建一个在您Client模型的方法,如果在客户端的医生任何first_session是真的,返回true,像...

def has_first? 
    self.doctors.each do |doctor| 
    return true if !doctor.first_session.nil? 
    end 
    return false 
end 

这是伪代码,并可能需要进行调整第一

0

这会起作用,但可能效率稍低一点,因为它在ruby中完成了一些工作,而不是在db中完成所有工作。

clients = Client.order('clients.id DESC').include(:doctors).select do |client| 
    client.doctors.all? {|doctor| doctor.first_session.nil? } 
end 

从逻辑上讲,应该取所有的客户端,然后在Ruby中,选择将评估该块中的条件和那些返回true,将被分配到客户的客户。

只有当该客户的所有医生都没有first_session时,条件块才会返回true。

希望有所帮助。使用子查询可能有更高效的方法,但是其语法可能取决于您使用的数据库。

2

这是那些为了找到不符合某些条件的记录的情况之一,您可以通过查找除符合条件的记录以外的所有记录来执行此操作。在SQL中,这是通过WHERE子句中的子查询完成的。

对于这样的情况,squeel gem非常有用,因为它封装了SQL的复杂性。这是我会怎么做(与squeel):

scope :visited_doctor, joins(:doctors).where { doctors.first_visit != nil } 
scope :not_visited_doctor, where { id.not_in(Patient.visited_doctor.select(:id)) } 

需要注意的是,你可以做到这一点没有squeel,但你必须让你的手(和你的代码)脏与SQL。

0

那么,我找到了一个涉及两个查询的解决方案。

avoid_ids_results = Doctors.select('client_id') 
         .where("first_session IS NOT NULL") 
         .map(&:client_id).join(', ') 

@clients = Clients. 
       joins(:doctors). 
       where('clients.id NOT IN (' + avoid_ids_results + ')'). 
       order('clients.id DESC') 

谢谢大家!

相关问题