Sql 反向查询有多个:通过
情景:Sql 反向查询有多个:通过,sql,ruby-on-rails,rails-activerecord,Sql,Ruby On Rails,Rails Activerecord,情景: Team has_many :players, dependent: :destroy has_many :users, through: :players Player belongs_to :team belongs_to :user User 那么,假设我有4个团队,拥有不同的用户: Team 1 User 1, User 2 Team 2 User 2, User 3 Team 3 User 1 Team 4 User 2, User 4, User 5 现在,假设
Team
has_many :players, dependent: :destroy
has_many :users, through: :players
Player
belongs_to :team
belongs_to :user
User
那么,假设我有4个团队,拥有不同的用户:
Team 1
User 1, User 2
Team 2
User 2, User 3
Team 3
User 1
Team 4
User 2, User 4, User 5
现在,假设我有两个用户的id,(用户1
,用户5
),我想知道是否有任何团队只由这两个玩家组成。假设我有一个由用户1、2和5组成的团队。查询不应导致此团队失败
如何使用ActiveRecord
语义来实现这一点?从一个团队中获得所有球员很容易,但我找不到相反的方法
Team.join(:users).where('users.id in (?)', [1,5]).
select { |team| team.users.map(&:id).sort == [1,5] }
先前的答案(针对预编辑的问题)
这对你有用吗
Team.join(:users).where('users.id in (?)', [1,5])
您可以通过以下方式在用户模型上执行相同的操作:
# user.rb
has_many :teams, through: :works
has_many :works, foreign_key: :user_id
回应您的编辑和评论
哈奇:
Team.join(:users).where('users.id in (?)', [1,5]).
select { |team| team.users.map(&:id).sort == [1,5] }
更好
可以使用两个where子句: 一个用于获取所有的
团队
,其中正好有两个用户
Team.joins(:users).group("teams.id").having("count('distinct users.id') = 2").select("teams.id")
其次是让所有团队
与1
和5
用户在一起
Team.joins(:users).where('users.id in (?)', [1,5]).group("teams.id").having("count('distinct users.id') = 2").select("teams.id")
这两者的交集应该能满足你的需要。
因此,要将这一切结合起来:
Team.where(id: Team.joins(:users).group("teams.id").having("count('distinct users.id') = 2").select("teams.id")).where(id: Team.joins(:users).where('users.id in (?)', [1,5]).group("teams.id").having("count('distinct users.id') = 2").select("teams.id"))
更新:啊!我是用纯SQL实现的:
users = User.first(2)
Team.joins(:users).group('teams.id').having('SUM( CASE WHEN users.id in (?) THEN 1 ELSE -1 END ) = ?', users, users.count)
试试看,让我知道它是否适合你(在这里工作:和相同的例子,但有3名玩家:)
这不是在DB级别优化的,因为它使用了大量ruby/rails代码,但是您能试试吗
users = User.first(2)
# find teams with that exact number of players associated
teams = Team.joins(:users).group('teams.id').having('COUNT(users.id) = ?', users.count)
# find players referencing to those teams with other users than the ones specified
players_to_ignore = Player.where(team_id: teams).where('user_id NOT IN (?)', users)
# get Teams where associated players id is not in the previous list
Team.where(id: teams).joins(:players).where('players.id NOT IN (?)', players_to_ignore)
他们是否必须在同一个团队中,可能与其他用户在一起,或者他们必须是该团队中唯一的玩家?@Yoshiji先生是该团队中唯一的玩家。这不起作用,因为我需要一个只有这两个玩家的团队。假设我有一个包含用户1、2和5的团队。这个查询也会带来这个团队。@MurifoX更新了答案上下文:我们正在寻找由用户1和2组成的团队。团队3有用户1和用户3。此团队#3将根据您的第一条指令找到(有2名玩家),然后再次找到,因为其中一名玩家在[1,2]中有id。我将尝试向您提供反馈