在ActiveRecord查询中包含所有ID

时间:2016-05-06 11:50:18

标签: mysql ruby-on-rails ruby activerecord

我正在开发一个游戏平台,我有以下(简化)模型:

class Game < ActiveRecord:Base
  has_many :game_players
  has_many :players, through: :game_players
end

class Player < ActiveRecord:Base
  has_many :game_players
  has_many :games, through: :game_players
end

class GamePlayer < ActiveRecord:Base
  belongs_to :game
  belongs_to :player
end

我需要执行一个ActiveRecord查询来查找某组用户所玩的所有游戏。例如,给定数据:

+---------+-----------+
| game_id | player_id |
+---------+-----------+
|      10 |        39 |
|      10 |        41 |
|      10 |        42 |
|      12 |        41 |
|      13 |        39 |
|      13 |        41 |
+---------+-----------+

我需要找到一种方法来确定具有ID 39和41的玩家玩哪些游戏,在这种情况下,这将是具有ID 10和13的游戏。我到目前为止找到的查询是:< / p>

Game.joins(:players).where(players: {id: [39, 41]}).uniq

然而,此查询返回任何这些玩家所玩的游戏,而不是两者所玩的游戏。

2 个答案:

答案 0 :(得分:1)

如果你可以执行两个查询并将结果相交,你可以尝试一下:

Game.joins(:players).where(players: {id: 39}) & Game.joins(:players).where(players: {id: 41}) 

答案 1 :(得分:1)

这个函数更像是一个SQL INTERSECT,并且在这种情况下应该为您提供所需的结果:

Game.joins(:players).where(players: {id: [39,41]}).group('"games"."id"').having('COUNT("games"."id") > 1')

真的,通过选择任一玩家正在玩的游戏然后按game.id进行分组以将结果减少到结果组中具有多个game.id的游戏,就会产生魔力。它从Rails控制台产生以下结果:

 => #<ActiveRecord::Relation [#<Game id: 10, created_at: "2016-05-07 01:17:25", updated_at: "2016-05-07 01:17:25">, #<Game id: 13, created_at: "2016-05-07 01:17:25", updated_at: "2016-05-07 01:17:25">]>

请注意,此解决方案仅返回游戏10和13(基于示例数据)。手动验证显示只有游戏10和13同时玩家39和41。