class GameSystem < ActiveRecord::Base
has_many :cartridges
end
class Cartridge < ActiveRecord::Base
belongs_to :game_system
end
我希望能够做到:
GameSystem.joins(:cartridges)
.where({:cartridge => { :name => 'Dragons Lair', :publisher => 'Cinematronics' })
.where({:cartridge => { :name => 'Zaxxon', :publisher => 'Sega' })
.limit(1)
换句话说,告诉我是否存在一个游戏系统,其中有一个由Cinematronics提供的Dragon's Lair硒鼓,以及一个名为Zaxxon by Sega的硒鼓......
是否有一种积极的记录友好的方式来做到这一点?
答案 0 :(得分:1)
您需要执行两个单独的JOINS或子查询。 如果你想要更多的Activerecord友好,你可以使用自动JOIN和自己编写的一个,如下所示:
GameSystem.joins(:cartridges)
.joins('JOIN cartridges AS c2 ON c2.game_system_id = game_systems.id')
.where('cartridges.name = ? AND cartridges.publisher = ?', 'Dragons Lair', 'Cinematronics')
.where('c2.name = ? AND c2.publisher = ?', 'Zaxxon', 'Sega')
或者使用子查询,它看起来像这样:
GameSystem.joins(:cartridges)
.where('cartridges.name = ? AND cartridges.publisher = ?', 'Dragons Lair', 'Cinematronics')
.where(id: GameSystem.joins(:cartridges)
.where('cartridges.name = ? AND cartridges.publisher = ?', 'Zaxxon', 'Sega'))
子查询更具可读性和清晰度,但有时根据您的数据库引擎可能会降低性能。你可以在这个非常完整的主题上阅读它,并决定你喜欢哪一个:Join vs. sub-query
答案 1 :(得分:0)
稍微触摸SQL
,您可以试试这个:
GameSystem.joins('JOIN cartridges AS cartridges1 ON cartridges1.game_system_id = game_systems.id')
.joins('JOIN cartridges AS cartridges2 ON cartridges2.game_system_id = game_systems.id')
.where('cartridges1.name = ? AND cartridges1.publisher = ?', 'Dragons Lair', 'Cinematronics')
.where('cartridges2.name = ? AND cartridges2.publisher = ?', 'Zaxxon', 'Sega').limit(1)
答案 2 :(得分:0)
由于您需要2种不同类型的墨盒名称,因此需要OR
。
GameSystem.joins(:cartridges)
.where("(cartridges.name = ? AND cartridges.publisher = ?) OR (cartridges.name = ? AND cartridges.publisher = ?)", 'Dragons Lair', 'Cinematronics', 'Zaxxon', 'Sega')
答案 3 :(得分:0)
要在子记录上过滤两个条件,您应该使用两个连接。 您无法通过单一连接实现此目的(即使使用纯SQL)。 ActiveRecord只是标准SQL的包装。
所以看起来应该是这样的:
GameSystem.joins('JOIN cartridges c1 ON c1.game_system_id = game_systems.id')
.joins('JOIN cartridges c2 ON c2.game_system_id = game_systems.id')
.where('c1.name = ? AND c1.publisher = ?', 'Dragons Lair', 'Cinematronics')
.where('c2.name = ? AND c2.publisher = ?', 'Zaxxon', 'Sega')
.any?
# => true/false output
# you can also use .to_a
# or continue filtering as well