pool_tournament
有多个pool_tournament_matches
,每个匹配属于多个users
。用户has_many pool_tournaments
和has_many pool_tournament_matches
。
has_many :pool_tournament_matches
belongs_to :pool_tournament
has_many :pool_tournament_match_users, class_name: 'PoolTournamentMatchUser'
has_many :users, through: :pool_tournament_match_users
has_many :pool_tournament_users, class_name: 'PoolTournamentUser'
has_many :pool_tournaments, through: :pool_tournament_users
has_many :pool_tournament_match_users, class_name: 'PoolTournamentMatchUser'
has_many :pool_tournament_matches, through: :pool_tournament_match_users
这里有2个has_many协会。一个在user
和pool_tournament
之间。另一个在pool_tournament_match
和user
之间。
我的查询是确定哪个pool_tournament_matches
只有1个用户。我的查询为我提供了匹配列表,但它为每个pool_tournament_match
执行了N + 1查询。
tournament.pool_tournament_matches.includes(:users).select { |m| m.users.count == 1 }
PoolTournamentMatch Load (0.6ms) SELECT "pool_tournament_matches".* FROM "pool_tournament_matches" WHERE "pool_tournament_matches"."pool_tournament_id" = $1 [["pool_tournament_id", 2]]
PoolTournamentMatchUser Load (0.6ms) SELECT "pool_tournament_match_users".* FROM "pool_tournament_match_users" WHERE "pool_tournament_match_users"."pool_tournament_match_id" IN (1, 2, 3, 4)
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (1, 2, 3, 4, 5, 6, 7, 8)
(0.8ms) SELECT COUNT(*) FROM "users" INNER JOIN "pool_tournament_match_users" ON "users"."id" = "pool_tournament_match_users"."user_id" WHERE "pool_tournament_match_users"."pool_tournament_match_id" = $1 [["pool_tournament_match_id", 1]]
(0.7ms) SELECT COUNT(*) FROM "users" INNER JOIN "pool_tournament_match_users" ON "users"."id" = "pool_tournament_match_users"."user_id" WHERE "pool_tournament_match_users"."pool_tournament_match_id" = $1 [["pool_tournament_match_id", 2]]
(0.7ms) SELECT COUNT(*) FROM "users" INNER JOIN "pool_tournament_match_users" ON "users"."id" = "pool_tournament_match_users"."user_id" WHERE "pool_tournament_match_users"."pool_tournament_match_id" = $1 [["pool_tournament_match_id", 3]]
(0.7ms) SELECT COUNT(*) FROM "users" INNER JOIN "pool_tournament_match_users" ON "users"."id" = "pool_tournament_match_users"."user_id" WHERE "pool_tournament_match_users"."pool_tournament_match_id" = $1 [["pool_tournament_match_id", 4]]
我也不介意使用RAW SQL,并且可以根据需要发布架构。
谢谢!
答案 0 :(得分:1)
你可以让SQL为你做计数。以下内容适用于Postgres(不确定其他数据库):
tournament.pool_tournament_matches
.select("pool_tournament_matches.*, COUNT(users.id) as user_count")
.joins("LEFT OUTER JOIN pool_tournament_match_users ON (pool_tournament_match_users.pool_tournament_match_id = pool_tournament_matches.id)")
.joins("LEFT OUTER JOIN users ON (pool_tournament_match_users.user_id = users.id)")
.group("pool_tournament_matches.id")
.select { |match| match.user_count > 0 }
.group
之前的所有内容都会产生一个查询,它会将'user_count'属性附加到它返回的pool_tournament_matches。因此,在内存中发生的最终.select
将解析结果,而无需执行额外的数据库调用。