Ruby on rails 为什么此AR sum查询返回的结果是预期结果的两倍?

Ruby on rails 为什么此AR sum查询返回的结果是预期结果的两倍?,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,我从AR查询中得到一个奇怪的结果。使用sum得到的结果是预期结果的两倍 一些背景 @parent.children.size => 1 @parent.children => [#<Child id: 1, date: "2016-01-01", quantity: 2>] @parent.children.group_by_month_of_year(:date).count #using groupdate gem => {1=>1, 2=>0, 3

我从AR查询中得到一个奇怪的结果。使用
sum
得到的结果是预期结果的两倍

一些背景

@parent.children.size
=> 1
@parent.children
=> [#<Child id: 1, date: "2016-01-01", quantity: 2>]
@parent.children.group_by_month_of_year(:date).count #using groupdate gem
=> {1=>1, 2=>0, 3=>0, 4=>0, 5=>0, 6=>0, 7=>0, 8=>0, 9=>0, 10=>0, 11=>0, 12=>0}
由于只有一个子记录的
数量
为2,查询应该返回
1=>2
,不是吗

我将如何调试这个

编辑 该查询生成以下SQL语句

SELECT DISTINCT SUM("purchases"."quantity") AS sum_quantity, 
EXTRACT(MONTH from date::timestamptz AT TIME ZONE 'Etc/UTC' - INTERVAL '0 second')::integer 
AS extract_month_from_date_timestamptz_at_time_zone_etc_utc_interv 
FROM "purchases" 
INNER JOIN "people" ON "purchases"."person_id" = "people"."id" 
INNER JOIN "events" ON "people"."id" = "events"."person_id" 
WHERE "events"."location_id" = $1 AND (date IS NOT NULL) 
GROUP BY EXTRACT(MONTH from date::timestamptz AT TIME ZONE 'Etc/UTC'  INTERVAL '0 second')::integer  
[["location_id", 1]]
具有以下关系

class Location
  has_many :events
  has_many :people, -> { distinct }, through: :events
  has_many :purchases, -> { distinct }, through: :people
end

class Event
  belongs_to :location
  belongs_to :person
end

class Person
  has_many :events
  has_many :purchases
end

class Purchase
  belongs_to :person
end
编辑2 在更改关系的定义方式(如下所示)后,sum查询将计算正确的结果

class Location  
  has_many :events
  has_many :people, -> { distinct }, through: :events
  def purchases
    Purchase.where( person_id: self.people.pluck(:id)
  end 
end

以这种方式聚合时,在关联中使用distinct无效。如果位置和购买之间存在多个连接路径,则distinct将应用于最终聚合结果,而不是底层未聚合结果集

我甚至不确定数据模型是否有效。如果您试图通过人员和事件获取每个位置的销售额,您如何知道该购买与特定事件以及特定位置相关

您不需要直接将事件id添加到购买中,或者隐式地将事件的时间范围与购买时间进行比较,从而将购买链接到人员和事件吗

编辑:

为了更好地理解你想做什么,这个怎么样

Purchase.where(person: Person.joins(:events).where(events: {location_id: @location.id}).uniq).
         group_by_month_of_year(:date).sum(:quantity)

它生成了什么SQL?@davidardridge我已经在问题中添加了SQL和关联。这是一个有点复杂的关系,因此可能需要改进查询?如果在同一个月内有跨多个年份的记录,您也会遇到问题。例如,一次购买发生在2015年1月1日,另一次购买发生在2016年1月17日,这两次购买将分为同一个月,而不是单独的月份。您可能需要按月份和年份分组。谢谢@david。数据模型是有效的。我想要所有与活动/地点相关联的人进行的购买,而不是所有与活动/地点相关联的购买。在本例中,多年分组不是问题。我仍然无法理解为什么当预期的响应是
2
时,查询会计算
4
。谢谢@david。根据您的建议,我已更改了关系的定义方式(请参见上面的编辑)。查询现在求和并返回预期结果。我很想更好地理解为什么会发生这种情况。特别是,我发现很难理解“后台”中的代码是如何工作的“上面的部分指出,sum唯一可用的值是
2
,而sum查询返回的是
4
。如果您有任何想法可以帮助我更好地理解这一点,我将不胜感激。@AndyHarvey只是您有多个从位置行到个人的潜在连接路径,因为它们可以通过多个事件与位置关联。这会导致聚合将行加倍(三倍等)。在聚合完成此操作后,将distinct应用于结果。
Purchase.where(person: Person.joins(:events).where(events: {location_id: @location.id}).uniq).
         group_by_month_of_year(:date).sum(:quantity)