我正在尝试让所有与医生关联的客户,但他们都没有开始他们的第一次会话(一个客户has_many医生,可以与他们每个人进行第一次会话)。
到目前为止,我有:
@clients = Client.joins(:doctors).where('doctors.first_session IS NULL').order('clients.id DESC')
但是,当客户有例如 2 名医生时,这不起作用。 第一个 doctor.first_session = null,但第二个不是。这种情况将返回客户端,并且它不希望它返回。
有什么想法吗?
在这种情况下,为了查找不满足特定条件的记录,您可以通过查找除满足条件的记录之外的所有记录来实现。在 SQL 中,这是通过 WHERE 子句中的子查询完成的。
对于这种情况,squeel gem 非常有用,因为它封装了 SQL 复杂性。这就是我会这样做的方式(带有尖叫声):
scope :visited_doctor, joins(:doctors).where { doctors.first_visit != nil }
scope :not_visited_doctor, where { id.not_in(Patient.visited_doctor.select(:id)) }
请注意,你可以不费吹灰之力地做到这一点,但你必须用SQL弄脏你的手(和你的代码)。
这将起作用,但效率可能稍低,因为它在 ruby 中完成一些工作,而不是在数据库中完成所有工作。
clients = Client.order('clients.id DESC').include(:doctors).select do |client|
client.doctors.all? {|doctor| doctor.first_session.nil? }
end
从逻辑上讲,这应该获取所有客户端,然后在 ruby 中,select 将评估块中的条件,并且那些返回 true 的客户端将被分配给客户端。
仅当该客户的所有医生的first_session为零时,条件块才会返回 true。
希望有帮助。使用子选择可能有一种更有效的方法,但语法可能取决于您使用的数据库。
好吧,我找到了一个涉及两个查询的解决方案。
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')
谢谢大家!
您可以在Client
模型中创建一个方法,如果客户医生的任何first_session为真,则返回true,例如...
def has_first?
self.doctors.each do |doctor|
return true if !doctor.first_session.nil?
end
return false
end
这是伪代码,可能需要先进行调整