1

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

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

根据我的计算,Molds 53、197 和 1204 都有一个 Scroll 模式,所以我应该能够编写以下 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 方式来进行此类查询吗?

4

1 回答 1

1

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

除此之外,我建议使用 Rails查询方法来获取所需的数据,而不是求助于 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 几乎相同,并产生相同的结果(同样,正确的结果具有三个结果)。

请注意,INNER JOIN genres g您的 SQL 部分在这里没有明确提及。只要您在和through上定义了关联,这就会起作用:MouldPattern

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

由于您告诉 RailsMouldPattern通过genres表关联,它知道如何构建正确的 SQL 查询将它们连接在一起。

希望有帮助。

于 2013-01-23T12:44:20.093 回答