Ruby on rails 为什么此AR sum查询返回的结果是预期结果的两倍?
我从AR查询中得到一个奇怪的结果。使用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
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)