Sql Rails—不在特定关联旁边的联接表中的记录的范围
我在Rails应用程序中有两个模型-Sql Rails—不在特定关联旁边的联接表中的记录的范围,sql,ruby-on-rails,ruby,rails-activerecord,jointable,Sql,Ruby On Rails,Ruby,Rails Activerecord,Jointable,我在Rails应用程序中有两个模型-锦标赛和玩家通过连接表关联: class Tournament < ApplicationRecord has_many :tournament_players has_many :players, through: :tournament_players end class Player < ApplicationRecord has_many :tournament_players has_many :tourname
锦标赛
和玩家
通过连接表关联:
class Tournament < ApplicationRecord
has_many :tournament_players
has_many :players, through: :tournament_players
end
class Player < ApplicationRecord
has_many :tournament_players
has_many :tournaments, through: :tournament_players
scope :selected, -> (tournament) { includes(:tournaments).where(tournaments: {id: tournament.id}) }
end
成功地找到所有已添加到锦标赛的玩家,将该锦标赛作为参数
我想要的是一个相反的作用域——返回所有尚未添加到给定锦标赛中的玩家。我试过了
scope :not_selected, -> (tournament) { includes(:tournaments).where.not(tournaments: {id: tournament.id}) }
但这会让很多相同的球员回归,我想是因为这些球员是作为其他比赛的一部分存在的。其SQL看起来类似于:
SELECT "players".*, "tournaments”.* FROM "players" LEFT OUTER JOIN
"tournament_players" ON "tournament_players"."player_id" =
"players"."id" LEFT OUTER JOIN "tournaments" ON "tournaments"."id" =
"tournament_players"."tournament_id" WHERE ("tournaments"."id" != $1)
ORDER BY "players"."name" ASC [["id", 22]]
SELECT "players”.*, "tournaments”.* FROM "players" LEFT OUTER JOIN
"tournament_players" ON "tournament_players"."player_id" =
"players"."id" LEFT OUTER JOIN "tournaments" ON "tournaments"."id" =
"tournament_players"."tournament_id" WHERE "tournaments"."id" IS NULL
ORDER BY "players"."name" ASC
我还尝试了关于如何使用的建议
但这似乎不起作用——它只是返回一个空数组,我想这也是因为玩家作为单独比赛的一部分存在于联接表中。其SQL看起来类似于:
SELECT "players".*, "tournaments”.* FROM "players" LEFT OUTER JOIN
"tournament_players" ON "tournament_players"."player_id" =
"players"."id" LEFT OUTER JOIN "tournaments" ON "tournaments"."id" =
"tournament_players"."tournament_id" WHERE ("tournaments"."id" != $1)
ORDER BY "players"."name" ASC [["id", 22]]
SELECT "players”.*, "tournaments”.* FROM "players" LEFT OUTER JOIN
"tournament_players" ON "tournament_players"."player_id" =
"players"."id" LEFT OUTER JOIN "tournaments" ON "tournaments"."id" =
"tournament_players"."tournament_id" WHERE "tournaments"."id" IS NULL
ORDER BY "players"."name" ASC
好的,试试这个:
includes(:tournaments).distinct.where.not(tournaments: {id: tournament.id})
好的,试试这个:
includes(:tournaments).distinct.where.not(tournaments: {id: tournament.id})
您需要做的是:
# player.rb
scope :not_selected, -> (tournament) do
joins("LEFT JOIN tournament_players tp ON players.id = tp.player_id AND tp.tournament_id = #{tournament.id}").where(tp: {tournament_id: nil})
end
如果Rails有更好的方法来编写带有附加条件的左连接查询
请注意:
eager\u load
。除了据我所知,它不支持自定义条件之外,它还会为所有相关对象创建模型,而您不需要这些模型您需要做的是:
# player.rb
scope :not_selected, -> (tournament) do
joins("LEFT JOIN tournament_players tp ON players.id = tp.player_id AND tp.tournament_id = #{tournament.id}").where(tp: {tournament_id: nil})
end
如果Rails有更好的方法来编写带有附加条件的左连接查询
请注意:
eager\u load
。除了据我所知,它不支持自定义条件之外,它还会为所有相关对象创建模型,而您不需要这些模型可能重复的“查看我的编辑”-从我可以看出,这些解决方案不太正确。您能显示生成的SQL吗?添加了SQL。我只是不能专心于我需要的搜索!可能重复的“查看我的编辑”-从我可以看出,这些解决方案不太正确。您能显示生成的SQL吗?添加了SQL。我只是不能专心于我需要的搜索!谢谢-但是
:not_selected
作用域引发此错误:ActiveRecord::StatementInvalid:PG::UndefinedTable:error:表“tournaments”的子句条目中缺少此项
您可以更改吗,相反,includes
putjoins
?否-改为获取此错误:ActiveRecord::StatementInvalid:PG::GroupingError:error:column“tournaments.id”必须出现在GROUP BY子句中或在聚合函数中使用
您可以尝试第二个选项吗?该选项只返回一个空数组。谢谢-但是:not_selected
范围引发此错误:ActiveRecord::StatementInvalid:PG::UndefinedTable:错误:表“tournaments”的子句条目中缺少
您可以更改吗,相反,includes
putjoins
?否-改为获取此错误:ActiveRecord::StatementInvalid:PG::GroupingError:error:column“tournaments.id”必须出现在GROUP BY子句中或用于聚合函数中
您可以尝试第二个选项吗?该选项只返回一个空数组。谢谢!不过,它也犯了一些错误。第一个是玩家
不知道传递给查找比赛中的非比赛
的参数是什么。第二个问题是,find\u not\u in\u锦标赛
未定义?此外,作用域缺少开头的do
。放弃它-我不清楚开始时的find\u not\u in\u锦标赛
方法调用的目的是什么,但如果没有它,这将非常有效。如果您将其编辑为包含缺少的do
,并删除find\u not\u in\u touring
,我会将其标记为正确答案。谢谢我从头开始写,我先写了一个方法,然后我读到你需要的是一个范围。我想我是赶时间。谢谢你的更新。谢谢你!不过,它也犯了一些错误。第一个是玩家
不知道传递给查找比赛中的非比赛
的参数是什么。第二个问题是,find\u not\u in\u锦标赛
未定义?此外,作用域缺少开头的do
。放弃它-我不清楚开始时的find\u not\u in\u锦标赛
方法调用的目的是什么,但如果没有它,这将非常有效。如果您将其编辑为包含缺少的do
,并删除find\u not\u in\u touring
,我会将其标记为正确答案。谢谢我从头开始写,我先写了一个方法,然后我读到你需要的是一个范围。我想我是赶时间。谢谢你的更新。