简体   繁体   中英

Order records through has_many relationship

Class Event  
has_many event_sessions

Class EventSessions  
belongs_to event

Event Sessions table:  
t.integer "event_id"
t.datetime "date_start"
t.datetime "date_end"

My goal is to:

  1. Filter events by a date range (eg April 5 - May 10, 2019)

  2. Order events by start date of earliest event session (ordering for soonest and latest). There is no limit to the number of sessions.

I'm running into the following issues:

  1. Duplicate events showing up after filtering and ordering (the number of duplicate events is equal to the number of event sessions associated with an event, so 3 event sessions result in 3 of the same event showing up).

  2. Unable to use .distinct to remove duplicates

I'm using postgresql if that makes any difference.

This is my current code:

events = joins(:event_sessions)
         .where(event_sessions: { date_start: date_start..date_end } )
         .order('event_sessions.date_start ASC')

I run into the following error when I try to use .distinct:
PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list

Additionally, I'm unable to use .uniq, because it does not work with .paginate (.uniq converts it to an array).

I've found a solution (thanks to Rails - Distinct ON after a join ):

join_query = EventSession.select("event_id, min(date_start) as date").group(1)
events = Event.joins("INNER JOIN (#{join_query.to_sql}) as unique_event_sessions ON events.id = unique_event_sessions.event_id")
            .where("date >= ?", date_start).where("date <= ?", date_end)
            .order('date ASC')

Add to the select clause even the event_sessions attributes in order to use distinct

events = joins(:event_sessions)
         .where(event_sessions: { date_start: date_start..date_end } )
         .order('event_sessions.date_start ASC')
         .select('events.*, event_sessions.*')
         .distinct

I found something that worked:

join_query = EventSession.select("event_id, min(date_start) as date").group(1)
events = Event.joins("INNER JOIN (#{join_query.to_sql}) as unique_event_sessions ON 
events.id = unique_event_sessions.event_id")
        .where("date >= ?", date_start).where("date <= ?", date_end)
        .order('date ASC')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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