2016-11-28 3 views
1

Мне нужно написать запрос, который учитывает только тех, кто ранее не посещал событие.Как написать следующий запрос в Rails?

Вот модели

class Individual < ActiveRecord::Base 
    has_many :attendances, dependent: :destroy 
    has_many :events, through: :attendances 
end 

class Attendance < ActiveRecord::Base 
    belongs_to :event 
    belongs_to :individual 
end 

class Event < ActiveRecord::Base 
    has_many :attendances, dependent: :destroy 
    has_many :individuals, through: :attendances 
end 

На мой взгляд, у меня есть 2 разных запросов. Каждый запрос измеряет посещаемость событий в течение каждого финансового года.

Запрос на FY 2015:

<%= Event.published.joins(:attendances => :individual).where( 
    :events => {:fiscal_session => "2014-10-01".."2015-09-30"} 
).distinct.count(:individual_id) %> 

Запрос на FY 2016:

<%= Event.published.joins(:attendances => :individual).where( 
    :events => { :fiscal_session => "2015-10-01".."2016-09-30"} 
).distinct.count(:individual_id) %> 

Проблема заключается в том, что запрос на FY 2016 года не игнорировать лиц, которые приняли участие в мероприятии в FY 2015.

Я использую postgresql, и я попытался написать области и вспомогательные методы, которые бы отфильтровывали людей, которые посещали в 2015 году. Но я просто не мог понять это.

Например, вот FY 2015:

<%= Individual.joins(attendances: :event).where( 
:events => {:fiscal_session => "2014-10-01".."2015-09-30"} 
).group('individuals.id').having('count(attendances.id) > 0').count %> 

Результат:

{2787=>1, 3469=>1} 

И это для FY 2016 года

<%= Individual.joins(attendances: :event).where( 
:events => {:fiscal_session => "2015-10-01".."2016-09-30"} 
).group('individuals.id').having('count(attendances.id) > 0').count %> 

Результат таков:

{2905=>1, 3444=>1, 2787=>1, 2790=>1, 2858=>1} 

Как видите, individual_id 2787 засчитывается дважды. Я не хочу считать 2787 в запросе на 2016 год.

Каков правильный способ достижения желаемого счета с помощью Rails и ActiveRecord?

+1

Чтобы убедиться, что я понимаю ваш вопрос, вы хотите, чтобы лица, которые посетили одно или несколько мероприятий в 2016 году, но посетили нулевые события в любой другой период времени? Если это правильно, я думаю, вам нужно будет объединить ваш текущий запрос с двумя запросами «НЕ IN», чтобы получить периоды времени до и после 2016 года. – Brad

+0

да, это именно то, что я хочу. Я НЕ знаком с НЕ В –

ответ

2

Я думаю, что лучший способ для вас, чтобы выполнить то, что вы хотите сделать, - это два запроса.

ignore_individuals = Event 
.published 
.joins(attendances: :individual) 
.where( 
    'events.fiscal_session <= ?', '2015-09-30' 
) 
.pluck(:individual_id) 

Event 
.published 
.joins(attendances: :individual) 
.where.not(individual_id: ignore_individuals) 
.where( 
    events: { fiscal_session: "2015-10-01".."2016-09-30" } 
).distinct.count(:individual_id) 
+0

Я подошел к нему таким образом ранее сегодня, за исключением использования области. Результат этого запроса дает то же самое, что и этот запрос: 'Event.published.where (события: {finance_session:" 2015-10-01 ".." 2016-09-30 "}) .distinct.count (: individual_id) ' –

+1

ага извините, да. Это не сработает для того, что вы хотите сделать. – jphager2

+0

так близко. Я получаю эту ошибку: 'column events.individual_id не существует' –

1

Я думаю, что вы ищете: Individual.includes(:events).where(events: { id: nil }).count

Это люди, которые никогда не посещали каких-либо событий.

+0

Точно. Это даст мне количество людей, которые не участвовали в мероприятии. Как я могу использовать это, чтобы получить количество людей, которые посещали только в 2016 году. –

+1

wow. Хороший вопрос: D – kriskova

1

Не положительный, но если вы ищете для подсчета людей, которые уже посетили мероприятие в 2016 году, и ваши таблицы имеют временные метки вы Я считаю, что вы можете сделать

Individual.joins(:attendances).where("attendances.created_at > ?", "01-01-2016").count

+0

Это даст мне счет всех посещаемости в 2016 году.Тем не менее, я не хочу считать любого человека, который также присутствовал в 2015 году. –

Смежные вопросы