如何在Rails中编写以下查询?

问题描述:

我需要编写一个查询,只计算以前没有参加事件的个人。如何在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个不同的查询。每个查询都会测量每个会计年度的事件出勤率。

查询风云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查询不会忽视,在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被计数两次。我不想在FY 2016的查询中计入2787

什么是通过Rails和ActiveRecord实现所需计数的正确方法?

+1

为了验证我理解您的问题,您希望在2016财年参加过一个或多个活动的个人,但是每隔一段时间都参加了零活动?如果这是正确的,我认为您必须将您当前的查询与两个“NOT IN”查询结合起来,以获得2016财年前后的时间段。 – Brad

+0

是的,这正是我想要的计数。我不熟悉NOT IN –

我认为最好的方法为了完成你想要做的事情就是用两个查询。

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(events:{fiscal_session:“2015-10-01”..“2016-09-30”}).distinct.count(: personal_id)' –

+1

对不起,是的。这不适合你想要做的事情。 – jphager2

+0

这是如此接近。我得到这个错误:'列events.individual_id不存在' –

我认为你正在寻找:Individual.includes(:events).where(events: { id: nil }).count

这些谁没有参加任何活动的人。

+0

没错。这会给我一些没有参加过活动的人数。我如何使用它来获得仅在2016年 –

+1

哇出席的人数。好问题:D – kriskova

不积极的,但如果你正在寻找谁已经在2016年参加的活动的个人的数量和你的表有时间戳你,我相信你能做到

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

+0

这会给我2016年所有参加人数的统计。不过,我不想指望2015年出席的任何人。 –