简体   繁体   English

MySQL / Rails-根据每个记录的属性动态查询表字段

[英]MySQL / Rails - Dynamically query a table field based on an attribute of each record

I've got a use case where I need to query for Appointment records based on their created_at or their start_on values. 我有一个用例,需要根据Appointment记录的created_atstart_on值查询Appointment记录。 There are two types of appointments: 'Estimate' and 'GLA (go look at)' , represented by a type field with values 0 and 1. 约会有两种类型: 'Estimate''GLA(go look at)' ,由值为0和1的type字段表示。

If the appointment is of type Estimate, the query needs to use the start_on field - and if the appointment is a GLA, the query needs to use the created_at field, as GLA's are not scheduled and don't have start_on values. 如果约会的类型为Estimate,则查询需要使用start_on字段;如果约会为GLA,则查询需要使用created_at字段,因为GLA尚未安排,并且没有start_on值。

Right now, I'm querying the data using a Rails scope to filter down properties who've had their last appointment from and to a certain date like so (the following shows 'from'): 现在,我正在使用Rails范围查询数据,以筛选出从最后一个约会开始到某个日期的属性,如下所示(以下显示“ from”):

scope :last_appointment_from, ->(date, type) {
  query = joins(:appointments)
  query = query.where('appointments.start_on = (
    SELECT MAX(appointments.start_on) 
    FROM appointments
    WHERE appointments.property_id = properties.id)')
  query = query.where('appointments.start_on >= ?', date)
  query
}

But this only queries the start_on value. 但这仅查询start_on值。

I've tried looking into doing GREATEST(MAX(start_on), MAX(created_at)) - but then I'm not sure how to know which field to know to use in the where('events.start_on >= ?', date) part. 我已经尝试着研究GREATEST(MAX(start_on),MAX(created_at))-但是后来我不确定如何知道在where('events.start_on >= ?', date)部分。

After typing this out, I thought of another possible workaround - to just create another database field that gets updated with the corresponding date on an active record callback based on what type of Appointment it is, called query_field or something (and run a script to set that value for all existing records) - and that way I can just query on that one field? 输入完此内容后,我想到了另一个可能的解决方法-仅创建另一个数据库字段,该字段将根据活动记录回调上的相应日期进行更新,该类型取决于约会的类型,称为query_field或类似内容(并运行脚本来设置所有现有记录的值),这样我就可以查询该字段了?

Any thoughts/help is greatly appreciated! 任何想法/帮助将不胜感激!

Since you already have a type field, it could be a use case for STI, ie same SQL schema for the model but different behavior on the ruby side. 由于您已经具有类型字段,因此它可能是STI的用例,即该模型的SQL模式相同,但在ruby方面的行为不同。

Note the "type" field may already be causing issues with rails that you may not have considered as this field generally is reserved specifically for Single Table Inheritance STI in rails. 请注意,“类型”字段可能已经引起了您可能没有考虑过的导轨问题,因为该字段通常是专门为导轨中的单表继承STI保留的。

If you use STI you could just write an accessor that pulls the correct field from the database and presents it for each model. 如果使用STI,则只需编写一个访问器即可从数据库中提取正确的字段,并为每个模型提供该字段。

I think this approach should work assuming that no appointment should have a created_at before its start_on unless it is GLA 我认为这种方法应该起作用,除非除非约会是GLA否则任何约会都必须在其start_on之前不包含created_at

scope :last_appointment_from, ->(date, type) {
  query = joins(:appointments)
  query = query.where('GREATEST(appointments.start_on, appointments.created_at) = (
    SELECT GREATEST(MAX(start_on), MAX(created_at)) 
    FROM appointments
    WHERE appointments.property_id = properties.id)')
  query = query.where('GREATEST(appointments.start_on, appointments.created_at) >= ?', date)
  query
}

I'm not very good with Rails but for the pure MySQL you could use a where like this: 我对Rails不太满意,但是对于纯MySQL,可以使用如下所示的位置:

WHERE (
        (appointments.created_at > date
             AND appointments.type = 1)
        OR 
        (appointments.start_on > date
             AND appointments.type = 0)
      )

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

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