ActiveRecord:选择符合HABTM组合的记录

时间:2015-04-15 22:43:39

标签: ruby-on-rails postgresql activerecord has-and-belongs-to-many

我有3个表/模型参与者,人口统计,参与者人口统计。

我想找到人口统计数据组合的参与者。

这是一个简单的例子:

让我们假设在某些UI中我试图过滤参与者列表。我选择以下人口统计选择。性别:男(id = 1),年龄:21-30岁(id = 7),年龄:31-40岁(id = 8)

这表明我希望男性在21-30岁或31-40岁之内

我想找到参与者,他们有一个参与者记录,其中demographic_id是7或8,并且他们还有一个参与者记录,其中demographic_id是1。

这个SQL语句是什么样的,ActiveRecord中有什么可以使这个选择看起来更好或更容易链接。

谢谢

编辑:为什么我会使用HABTM似乎有些混乱。在该系统中,最终用户可以创建他们想要跟踪的任何人口统计数据。不仅仅是我预定义的并以表格形式放在桌子上。例如,用户可能想要开始跟踪参与者的“口头语言”。因此,他们会为每个“英语”,“西班牙语”,“德语”,“等”添加“口语”类别和人口统计。因为人们可以说多种语言,所以我可以通过联接表将参与者链接到英语和西班牙语。这就是联接表是必要的原因。

3 个答案:

答案 0 :(得分:0)

假设您的用例是参与者有一个人口统计(一个模型中包含的一组详细信息)

class Participant < ActiveRecord::Base
    has_one :demographic
end

class Demographic < ActiveRecord::Base
    belongs_to :participant
end

人口统计信息的create_table需要包含t.belongs_to :participant来创建Rails用于识别关系的外键。

现在得到你的答案:

my_array = Parcipant.demographic.where("gender = '%s' AND age = '%s' AND age = '%s'", gender_id, age_id_A, age_id_B ) 

引用here以获取有关.where子句的说明。

答案 1 :(得分:0)

好的,澄清每个人口统计代表参与者特征。我对这是否理想有所保留,例如你的问题意味着你有一个男性人口统计模型和第二个女性人口统计模型。然而,这是详细的,并没有改变如何设置参与者和人口统计学之间关系的实质,无论人口统计学代表什么。

参与者拥有并且属于许多人口统计数据,而人口统计数据属于许多参与者。

需要两种型号。

class Participant < ActiveRecord::Base
    has_and_belongs_to_many :demographics
end

class Demographic < ActiveRecord::Base
    has_and_belongs_to_many :participants
end

需要三个表,这里只需一次迁移,但您可能更喜欢单独迁移。

class SampleMigration < ActiveRecord::Migration

  def change
    create_table :participants do |t|
        t.string :name
    end

    create_table :demographics do |t|
        t.string  :name
    end

    create_table :demographics_participants, id: false do |t|
       t.belongs_to :demographic
       t.belongs_to :participant
    end
  end
end

照顾复数,Rails期待它们。它们在引用例如has_and_belongs_to_many :participants和命名表create_table :demographics时出现在此处。另外请注意,连接表名称是复数并按字母顺序排列。如果以相反的顺序放置名称,Rails将找不到该表。

participant.demographics现在将返回您的参与者拥有的一系列人口统计模型。虽然demographic.participants返回参与者模型数组。例如,Demographic.find(1).participants将返回一系列参与者模型,这些模型都是男性。

有关如何创建更复杂查询的建议,请参阅此Rails guide

答案 2 :(得分:0)

感谢Matt的努力。我可能不应该强调这一点,而是强调活动记录。我认为这让你相信我是一个ruby / rails新手。不是这样的。这个问题的难点在于sql。我需要找到符合人口统计特征的参与者。您提供的解决方案仅允许查找与之匹配的解决方案。以下是我正在使用的当前AR查询。只要参与者不能拥有来自一个类别的两个或更多人口统计数据,该查询就会起作用,例如上面的口语示例。这是因为如果参与者匹配来自类别的多个人口统计数据,则having子句中的计数值不再准确。

Participants.joins(:participant_demographics)
.where("participant_demographics.demographic_id = 3 OR participants_demographics.demographic_id = 1 OR participant_demographics.demographic_id =4")
.having('COUNT(participants.id) > 2')
.group('participants.id')