【问题标题】:how to do a search across many to many tables with rails 3如何使用rails 3在多对多表中进行搜索
【发布时间】:2013-01-06 21:42:02
【问题描述】:

我有三个表格,其中包含通过流派表格链接在一起的模具(模具)及其图案的详细信息:

Mould table
id : integer
name : string


Pattern table
id : integer
name : string

genres table
id : integer
mould_id :integer
pattern_id : integer

我在表格中有如下数据

Mould table
ID          Name
1           A1
2           A2
3           A3
53          A4
54          A5
197         A6
198         A7
1204        A8
1205        A9

Pattern Table

ID         Name
1          Running
2          Scroll

Genres Table

ID     mould_id  pattern_id
1       1           1
2       2           1
3       3           1
4       53          1
5       53          2
6       54          1
7       197         2
8       198         1
9       1204        2
10      1205        1

根据我的计算,模具 53、197 和 1204 都有滚动模式,所以我应该能够编写以下 SQL 来给出它

SELECT m.id   FROM moulds m INNER JOIN genres g
ON m.id = g.mould_id INNER JOIN patterns p
ON g.pattern_id = p.id  
WHERE p.id = 2     
GROUP BY m.id    
HAVING COUNT(*) >= 1

但它只返回 197 所以那里有问题(或我的数据)

然后将它转换为 Rails,我将它包装在一个 find_by_sql 中,它给出了相同的结果(这是有道理的)

有人可以帮助处理 SQL 或建议一种更好的 Rails 方式来执行此类查询吗?

【问题讨论】:

  • 我已经测试了你这里的东西,它对我有用(返回你提到的三个模具)。与我的测试唯一不同的是,我使用了mould_ids,范围从 1 到 9(映射 53 到 4、54 到 5 等)。所以我怀疑你的数据有什么奇怪的地方。

标签: sql ruby-on-rails search many-to-many


【解决方案1】:

我已经测试了您上面的模型和数据,我得到了您期望的结果(即名称为“A4”、“A6”和“A8”的三个模具)。所以我怀疑你的数据有问题。

除此之外,我建议使用 Rails query methods 来获取所需的数据,而不是求助于 SQL。例如,这个:

Mould.select('moulds.id')\
     .joins(:patterns)\
     .where('patterns.id' => 2)\
     .group('moulds.id')\
     .having('COUNT(*) >= ?', 1)

将生成此 SQL:

SELECT moulds.id FROM "moulds"
INNER JOIN "genres" ON "genres"."mould_id" = "moulds"."id"
INNER JOIN "patterns" ON "patterns"."id" = "genres"."pattern_id"
WHERE "patterns"."id" = 2
GROUP BY moulds.id
HAVING COUNT(*) >= 1

这与您拥有的 SQL 几乎相同,并产生相同的结果(同样,正确的结果具有三个结果)。

请注意,您的 SQL 的 INNER JOIN genres g 部分出现在此处而没有明确提及。只要您在MouldPattern 上定义了through 关联,这将起作用:

class Mould < ActiveRecord::Base
  has_many :genres
  has_many :patterns, :through => :genres
  #...
end

class Pattern < ActiveRecord::Base
  has_many :genres
  has_many :moulds, :through => :genres
  #...
end

既然您告诉 Rails MouldPattern 是通过 genres 表关联的,它就知道如何构建正确的 SQL 查询以将它们连接在一起。

希望对您有所帮助。

【讨论】:

  • 嗨盐山。非常感谢您的回复。我将其标记为正确答案,因为它确实有助于使用 rails 的做事方式,而不是求助于 SQL。尽管使用我的数据运行时我仍然只得到一个结果,而且我发布的样本只是记录的一个子集。不知道这里哪里出了问题。感谢您的帮助
  • 不客气!也不知道出了什么问题,就像我说的那样,我实际上输入了您发布的数据并对其运行查询,并且它起作用了。我唯一改变的是模具上的 ID,我将其映射到 1-9。如果您只是尝试在干净的数据库上进行测试呢?
  • 您得到的结果也可能与您使用的数据库类型有关。我在 sqlite3 中测试过。
  • 数据肯定有问题。处理一组干净的数据,它给出了预期的结果。是时候深入挖掘旧数据了。感谢您的帮助。
猜你喜欢
  • 2011-09-13
  • 1970-01-01
  • 1970-01-01
  • 2016-01-24
  • 2021-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多