Mysql 如何通过连接表中的一对引用查找记录?
有两个模型Player和Team相互关联,因此模式包含三个表Mysql 如何通过连接表中的一对引用查找记录?,mysql,sql,ruby-on-rails,postgresql,activerecord,relational-division,Mysql,Sql,Ruby On Rails,Postgresql,Activerecord,Relational Division,有两个模型Player和Team相互关联,因此模式包含三个表Player、Player\u teams和teams。 鉴于每支球队可能由1名或2名球员组成,如何通过已知球员id找到一支球队 在这种情况下 对球员id 1和2的查询应返回id为1的球队 对球员id 2的查询应返回id为1和2的球队 对球员id 3的查询应返回id为3的球队 这就是你要找的吗 select t.name from teams t inner join players_teams pt on t.id = pt.t
Player
、Player\u teams
和teams
。
鉴于每支球队可能由1名或2名球员组成,如何通过已知球员id找到一支球队
在这种情况下
- 对球员id 1和2的查询应返回id为1的球队
- 对球员id 2的查询应返回id为1和2的球队
- 对球员id 3的查询应返回id为3的球队
- 这就是你要找的吗
select t.name
from teams t
inner join players_teams pt on t.id = pt.team_id
where pt.player_id = 1
--“好的,请给我一个球队id,这两名球员在哪里一起踢球”
您可以尝试以下代码:
DECLARE @player_id_to_search INT
SET @player_id_to_search = 1
SELECT DISTINCT teams.name
FROM teams
JOIN players_teams ON players_teams.team_id = teams.id
JOIN players ON players.id = players_teams.player_id
AND players.id = @player_id_to_search
我认为你问题陈述的第三个要点有错误。没有第三队。在第三种情况下,我认为你想要返回第二队。(球员3所在的唯一球队。) 此查询需要2位信息—您感兴趣的玩家和玩家数量
SELECT team_id, count(*)
FROM players_teams
WHERE player_id IN (1,2)
GROUP BY team_id
HAVING count(*) = 2
-- returns team 1
SELECT team_id, count(*)
FROM players_teams
WHERE player_id IN (2)
GROUP BY team_id
HAVING count(*) = 1
-- returns teams 1 & 2
SELECT team_id, count(*)
FROM players_teams
WHERE player_id IN (3)
GROUP BY team_id
HAVING count(*) = 1
-- returns team 2
编辑:这里有一个通过ruby使用的例子,这可能会让它的工作原理更清晰一些
player_ids = [1,2]
sql = <<-EOF
SELECT team_id, count(*)
FROM players_teams
WHERE player_id IN (#{player_ids.join(',')})
GROUP BY team_id
HAVING count(*) = #{player_ids.size}
EOF
player_id=[1,2]
sql=这是一个简单的例子。我们在此汇集了一系列可能的技术:
虽然当前接受答案中的查询应该有效,但对于您的每个示例,这些查询应该更短更快:
SELECT team_id -- returns team 1
FROM player_teams pt1
JOIN player_teams pt2 USING (team_id)
WHERE pt1.player_id = 1
AND pt2.player_id = 2;
SELECT team_id -- returns team 1 and 2
FROM player_teams
WHERE player_id = 2;
SELECT team_id -- returns team 2 (and 3 in the improved fiddle)
FROM player_teams
WHERE player_id = 3;
在案例2和案例3中,根本不需要通过
/加入
/分组
但是,如果您希望查找仅由玩家3组成的团队(而不包括其他成员),请使用以下命令:
SELECT pt1.team_id -- returns team 3
FROM player_teams pt1
LEFT JOIN player_teams pt2 ON pt2.team_id = pt1.team_id
AND pt2.player_id <> pt1.player_id
WHERE pt1.player_id = 3
AND pt2.player_id IS NULL;
我把这两个箱子都加进去了。总的来说可能会慢一点,而且肯定比只查询一个player\u id
要慢一点,感谢您创建了fiddle并清楚地解释了场景。通过单击答案左侧的勾号符号接受对您有效的答案,以便关闭该答案。大致来说,“这两名玩家参与的团队”是什么意思?如果您需要查找给定多个玩家的团队,您可以将变量@player_id_to_search的数据类型更改为字符串,并修改最后一行的条件。除了团队中有两名球员时的查询:“好的,SQL给我一个团队id,这两名球员一起玩过”谢谢你,Alex,我确实错过了第三队。该场景涵盖了团队中只有一名玩家的情况,这与第二个场景不同,第二个场景中有一名玩家参与两个团队。np,容易输入错误。我发布的查询将在所有这三种情况下给出正确答案。你能解释一下这些查询的魔力吗?是否在count(*)语句中?他们是如何工作的?使用count(*),您会说“我指定的一组球员中有多少人是每个团队的成员?”。您可以通过在不使用HAVING子句的情况下运行查询来查看这个interm结果。在计算完这个结果集之后,HAVING子句会删除发现的玩家总数不等于您要查找的玩家数量的任何团队。整洁!我非常后悔跳过了一个SQL类:(感谢您系统化的方法@Erwin!在需要时,可以通过将NULL
交换到第二个玩家id来使用最后一个查询作为通用解决方案吗?@lessless:我添加了一些来解决这个问题。(还要注意我修复的拼写错误。)
SELECT pt1.team_id -- returns team 3
FROM player_teams pt1
LEFT JOIN player_teams pt2 ON pt2.team_id = pt1.team_id
AND pt2.player_id <> pt1.player_id
WHERE pt1.player_id = 3
AND pt2.player_id IS NULL;
SELECT pt1.team_id -- returns team 3
FROM player_teams pt1
LEFT JOIN player_teams pt2 ON pt2.team_id = pt1.team_id
AND pt2.player_id <> pt1.player_id
WHERE pt1.player_id = 3
AND pt2.player_id IS NOT DISTINCT FROM 2;