Rails 使用活动记录复杂查询执行内部连接

Rails perform inner join with active record complex query

我必须执行复杂的活动记录查询。

我有 5 个模型

卡片模型

class Card < ActiveRecord::Base
  has_many :leads
  has_many :programs, through: :leads
end

潜在客户模型

class Lead < ActiveRecord::Base
  belongs_to :card
  belongs_to :program
end

程序模型

class Program < ActiveRecord::Base
  has_many :leads
  has_many :cards, through: :leads
  belongs_to :school
end

学校模型

class School < ActiveRecord::Base
  has_many :programs
  belongs_to :representative
end

代表车型

class Representative < ActiveRecord::Base
  has_many :schools
end

我想统计每个学校和每个代表有多少张卡片。一个代表有很多学校,一个学校有很多节目,一个节目有很多卡片。

我知道我必须执行内部联接,但经过一些研究后我还没有找到任何精确的说明。谢谢你的帮助。

为您的某些模型添加更多关联应该会有所帮助。

class School < ActiveRecord::Base
  # in addition to existing relations
  has_many :leads, through: :programs
  has_many :cards, through: :leads
end

class Representative < ActiveRecord::Base
  # in addition to existing relations
  has_many :programs, through: :schools
  has_many :leads, through: :programs
  has_many :cards, through: :leads
end

那么,简单的获取单个学校或代表的卡片数量的方法应该很简单。

@school.cards.count
@representative.cards.count

如果您想获得唯一卡片的数量,即一张卡片可能与同一学校或代表内的多个项目相关联,并且您希望每个卡片只计算一次,请使用 distinct.

@school.cards.distinct.count
@representative.cards.distinct.count

现在,如果您想获得每个学校和代表拥有的卡片数量,这有点棘手,但仍然有可能。

@schools = School.select('schools.*, count(cards.id)')
                 .joins(programs: { leads: :card } )
                 .group(:id)

@reps = Representative.select('representative.*, count(cards.id)')
                      .joins(schools: { programs: { leads: :card } } )
                      .group(:id)

如果您希望每所学校或代表的卡片数量唯一,只需在适当的查询中将 count(cards.id) 更改为 count(distinct cards.id)


关于这些解决方案的几点说明:

  • 如果学校或代表有 张卡片,它们将不会出现在 @schools@representatives 变量中。为了使它们出现,您需要稍微调整查询并使用 LEFT JOIN.
  • 您可能甚至不需要在 SchoolRepresentative 模型中关联到 :cards 来获得计数;您可能只使用 :leads 关联。但是,这会使区分变得更加困难,所以这就是我选择 :cards.
  • 的原因