如何通过连接表中的引用对找到记录?

时间:2015-11-25 02:51:38

标签: mysql sql ruby-on-rails postgresql activerecord

有两个模型Player和Team彼此关联为多对多,因此架构包含三个表playersplayer_teamsteams。 鉴于每支球队可能由1或2名球员组成,如何通过已知球员ID找到球队?

在这个SQLFiddle http://sqlfiddle.com/#!15/27ac5

  • 对玩家ID 1和2的查询应返回ID为
  • 的小组
  • 对玩家ID 2的查询应返回具有ID 1和2
  • 的团队
  • 查询玩家ID 3应该返回ID为
  • 的小组

4 个答案:

答案 0 :(得分:2)

我认为问题陈述的第三个要点是错误的。没有球队3.在第三种情况下,我认为你想要回归球队2.(球员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

答案 1 :(得分:1)

这是你在找什么?

select t.name 
from teams t 
inner join players_teams pt on t.id = pt.team_id
where pt.player_id = 1

- “好的,SQL给了我一个团队ID,这两个玩家都在一起玩”

select pt1.team_id
from players_teams pt1
inner join players_teams pt2 on pt1.team_id = pt2.team_id
where pt1.player_id = 1
and pt2.player_id = 2

答案 2 :(得分:1)

这是的简单案例。我们在这里汇集了一系列可能的技术:

虽然当前接受的答案中的查询应该有效,但对于每个示例,这些查询应该更短更快:

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中,根本不需要JOIN / GROUP BY / HAVING

如果,您想要找到仅由播放器3 (以及其他成员)组成的团队,请使用:< / p>

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;

根据你的定义,这似乎不太可能:

  

鉴于每支球队可能由1或2名球员组成

相关:

SQL Fiddle改进了架构和扩展测试用例。

值得注意的是,我添加了FK约束并将UNIQUE索引替换为PRIMARY KEY约束。更多信息:

通用查询

要使同一查询适用于两个player_id或一个player_idNULL,请使用NULL安全比较运算符IS NOT DISTINCT FROM

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;

我把两个案子都添加到小提琴里。总体来说可能会慢一点,并且肯定比只有一个player_id的简单查询慢。

答案 3 :(得分:0)

您可以尝试以下代码:

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