【问题标题】:Get parent objects without active childs获取没有活动子对象的父对象
【发布时间】:2017-12-08 15:57:21
【问题描述】:

我有两个模型,DoctorDoctorClinic 其中一个 doctor has_many clinics

doctor.rb:

has_many :clinics, class_name: 'DoctorClinic', dependent: :destroy

doctor_clinic.rb

belongs_to :doctor

DoctorClinicdoctor_id 和一个布尔值 active 字段。

我想要什么:

我想获取所有没有任何活动(active 字段为true)诊所的doctors。如果一个医生有两个诊所,其中一个处于活动状态,另一个处于非活动状态,则不应选择医生。

如果出现以下情况,将选择医生记录,

  • 根本没有诊所
  • 如果有任何诊所但都处于非活动状态,即所有诊所都有activefalse

如果出现以下情况,将不会选择医生,

  • 有任何活跃的诊所。

到目前为止我所做的尝试:

尝试 1:

scope :incomplete_doctors, -> { includes(:clinics)
                                .where("( doctor_clinics.id IS NULL ) OR
                                        ( doctor_clinics.id IS NOT NULL AND
                                            doctor_clinics.active=?)", false )
                              }

尝试 2:

scope :incomplete_doctors, -> { where("id NOT IN (?)", self.includes(:clinics)
                            .where("( doctor_clinics.doctor_id IS NULL ) OR
                                      ( doctor_clinics.doctor_id IS NOT NULL AND
                                          doctor_clinics.active=?)", false )
                            .select(:id))
                            }

尝试 3:

SELECT "doctors".* FROM "doctors"
  LEFT OUTER JOIN "doctor_clinics" ON "doctor_clinics"."doctor_id" = "doctors"."id"
  WHERE ( ( doctor_clinics.id IS NULL ) OR
          ( doctor_clinics.id IS NOT NULL AND
              doctor_clinics.active='f'))
  GROUP BY doctors.id
    HAVING 'true' <> ANY(array_agg(DISTINCT doctor_clinics.active::TEXT));

成功:

我可以使用以下方法实现所需的输出,但我想使用 SQL 查询来实现。

def active_clinics
  clinics.active_clinics # active_clinics is a scope in Clinic model while give all active clinics
end

def self.incomplete_doctors
  (Doctor.all.map { |d| d unless d.active_clinics.present? }).compact
end

【问题讨论】:

  • 这行得通吗? left_outer_joins(:doctor_clinics).where( 'doctor_clinics.id = ? OR doctor_clinics.active = ?', nil, false ) 范围为 Doctor.unassociated
  • 不。当有两个clinics,一个处于活动状态,另一个处于非活动状态时,它会失败。在这种情况下,不应选择医生。我刚刚在问题中添加了更多信息。
  • @Md.FarhanMemon,另外,left_outer_joins 不起作用(至少在 Rails 3 中),includes 等效于 left_outer_join。所以,我将该范围更新为{includes(:clinics).where( 'doctor_clinics.id = ? OR doctor_clinics.active = ?', nil, false ) }

标签: sql ruby-on-rails ruby postgresql ruby-on-rails-3


【解决方案1】:

这样的东西应该可以在纯 SQL 中解决问题

SELECT * 
FROM doctors
WHERE NOT EXISTS (
  SELECT 1
  FROM doctor_clinics
  WHERE 
    doctor_clinics.doctor_id = doctors.id 
    AND doctor_clinics.active = true 
)

您应该可以将它与find_by_sql 一起使用:

Doctor.find_by_sql(SQL)

没有 Rails 3 项目来实际测试它;-)

【讨论】:

  • 感谢您的反馈。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-15
  • 1970-01-01
  • 1970-01-01
  • 2020-01-26
  • 2022-01-04
  • 1970-01-01
相关资源
最近更新 更多