首页 > 解决方案 > Rails:使用内连接查询,按关联排序,没有重复记录

问题描述

因此,我正在尝试创建在我的应用程序中搜索约会的功能,并且在重复记录和订购方面遇到了麻烦。

总结一下:

约会是在两个用户之间进行的,一个是正在预订的booker,一个是bookee正在预订的。An appointment also has_many :time_optionsthat a user can suggest, and then when the bookeeselects and confirms one of these suggested time_optionsthe start_timeis applied to the similar start_timeattribute on appointments. 模型的结构如下:

#appointment.rb
belongs_to :booker, foreign_key: :booker_id, 
                                class_name: 'Profile'
belongs_to :bookee, foreign_key: :bookee_id, 
                                class_name: 'Profile'
has_many :time_options, dependent: :destroy

scope :order_by_start_time, -> {
               joins(:time_options)
               .order("COALESCE(appointments.start_time, time_options.start_time) DESC")
              }

def self.search(search)
  if search
    search_term = "%#{search}%"
    joins(
          "INNER JOIN profiles ON profiles.id IN (appointments.booker_id, 
                                                  appointments.bookee_id)"
         )
    .where(
           "CONCAT_WS(' ', profiles.first_name, profiles.last_name) ILIKE :term 
            OR appointments.service_title ILIKE :term", 
            term: search_term
           )
  else
    where(nil)
  end
end
#time_option.rb 
 belongs_to :appointment, touch: true
 belongs_to :profile

#profile.rb
 belongs_to :user, touch: true
 has_many :booker_appointments, foreign_key: :booker_id,
                                class_name: 'Appointment', 
                                dependent: :nullify
 has_many :bookee_appointments, foreign_key: :bookee_id, 
                                class_name: 'Appointment', 
                                dependent: :nullify

我试图让用户通过他们的约会service_title或其他用户的姓名(无论他们是booker还是bookee)来搜索约会。然后,我想按 . 对这些搜索结果进行排序start_time。约会本身的 (仅在确认约会时设置),或者start_time如果约会尚未确认并且它start_timenil,则改为使用最早start_time的相关time_options.

所以在控制器中,我正在做类似的事情:

  def index
    @appointments = Appointment.all_profile_appointments(@profile)
    if params[:search]
      @upcoming_appointments = @appointments.search(params[:search])                             
                                            .order_by_start_time
                                            .page(params[:page])
                                            .per(12)
    else
      @upcoming_appointments = @appointments.order_by_start_time
                                            .page(params[:page])
                                            .per(12)
      end
    end

但是,我的搜索方法返回重复项,我相信是因为INNER JOIN. 如果我在.distinct之前或之后添加order_by_start_time method,我会得到一个很棒的错误:PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list

所以我很确定我只需要编写一个更复杂、更精确的 SQL 语句;但是,在需要加入profiles表以按名称搜索之间,需要加入/合并time_options表以按顺序排序,start_time我不太确定下一步该去哪里。作为背景,我使用postgresql的是 Rails 4。

TL;DR:我正在尝试按预约或被预约的个人资料的名称搜索预约记录。然后,我希望通过 订购该查询appointments.start_time,或者如果没有确认预约 start_time,则按time_options.start_time与预约相关联的最早时间订购。我试图在没有一堆重复记录的情况下做到这一点。

标签: sqlruby-on-railspostgresqlactiverecord

解决方案


推荐阅读