MySQL成对查询

MySQL成对查询,mysql,select,join,Mysql,Select,Join,如何选择尚未与“alpha”配对的所有玩家?输出='伽马'。即使pairs表为空,它也应该工作 table: players +----------+-------+ | playerID | name | +----------+-------+ | 1 | alpha | | 2 | beta | | 3 | gamma | +----------+-------+ table: pairs +---------+---------+ | pl

如何选择尚未与“alpha”配对的所有玩家?输出='伽马'。即使pairs表为空,它也应该工作

table: players
+----------+-------+
| playerID | name  |
+----------+-------+
|        1 | alpha |
|        2 | beta  |
|        3 | gamma |
+----------+-------+

table: pairs
+---------+---------+
| player1 | player2 |
+---------+---------+
|       2 |       3 |
|       1 |       2 |
+---------+---------+
我已经挣扎了好几个小时了。例如,如果我这样做

SELECT p.*, r.*
FROM players p
JOIN pairs r
    ON (player1 = playerID) OR (player2 = playerID)
WHERE
    ((r.player1 != 1) AND (r.player2 != 1));
输出为“beta”和“gamma”。在联接中,“beta”与“alpha”和“gamma”配对出现两次,每次一次。WHERE条件消除了一行“beta”。我想要的是消除所有“beta”行。我是新来的,尝试了各种组合的小组,有等,我无法让它工作


类似的东西应该适用于这种情况

SELECT
    pl.*
FROM 
    players as pl
WHERE 
    pl.playerID NOT IN 
    (
      SELECT 
          p.player2
      FROM
          pairs AS p
      INNER JOIN 
          players plr ON plr.playerID = p.player1
      WHERE 
          plr.name='alpha'

    )

如果pairs表中的player1和player2列的位置发生变化,您可能必须在子查询中使用case。

类似的内容应该适用于这种情况

SELECT
    pl.*
FROM 
    players as pl
WHERE 
    pl.playerID NOT IN 
    (
      SELECT 
          p.player2
      FROM
          pairs AS p
      INNER JOIN 
          players plr ON plr.playerID = p.player1
      WHERE 
          plr.name='alpha'

    )
如果pairs表中的player1和player2列的位置发生变化,您可能必须在子查询中使用case。

这应该可以做到:

drop table pair;
drop table player;

create table player (
    id int,
    name varchar(32)
);

create table pair (
    id1 int,
    id2 int
);

insert into player values (1, 'Andy');
insert into player values (2, 'Bob');
insert into player values (3, 'Carl');
insert into player values (4, 'Dave');

insert into pair values (2, 3);
insert into pair values (1, 2);
insert into pair values (3, 1);

select * from player where id not in (
select
    if(pair.id1 = player.id, pair.id2, pair.id1) as other_player
from 
    pair
    join player on pair.id1 = player.id or pair.id2 = player.id
where
    player.name = 'Andy'
) 
;
这应该做到:

drop table pair;
drop table player;

create table player (
    id int,
    name varchar(32)
);

create table pair (
    id1 int,
    id2 int
);

insert into player values (1, 'Andy');
insert into player values (2, 'Bob');
insert into player values (3, 'Carl');
insert into player values (4, 'Dave');

insert into pair values (2, 3);
insert into pair values (1, 2);
insert into pair values (3, 1);

select * from player where id not in (
select
    if(pair.id1 = player.id, pair.id2, pair.id1) as other_player
from 
    pair
    join player on pair.id1 = player.id or pair.id2 = player.id
where
    player.name = 'Andy'
) 
;

我会把它分解成小块,然后拼凑起来。首先获取alpha玩家的id:

SELECT playerID
FROM players
WHERE name = 'alpha';
下一步将是找出如何排除。我会得到所有与玩家1配对的玩家的列表。我通过选择player1为“alpha”的所有player2值和player2为“alpha”的所有player1值来实现这一点,如下所示:

SELECT p.player2
FROM pairs p
JOIN(
  SELECT playerID
  FROM players
  WHERE name = 'alpha') b ON b.playerID = p.player1
UNION
SELECT p.player1
FROM pairs p
JOIN(
  SELECT playerID
  FROM players
  WHERE name = 'alpha') b ON b.playerID = p.player2;
一旦你做到了这一点,剩下的唯一一步就是从玩家那里拉,玩家1不是阿尔法,2不在上面的列表中:

SELECT *
FROM players
WHERE playerID NOT IN(
  SELECT playerID
  FROM players
  WHERE name = 'alpha') 
AND playerID NOT IN(
  SELECT p.player2
  FROM pairs p
  JOIN(
    SELECT playerID
    FROM players
    WHERE name = 'alpha') b ON b.playerID = p.player1
  UNION
  SELECT p.player1
  FROM pairs p
  JOIN(
    SELECT playerID
    FROM players
    WHERE name = 'alpha') b ON b.playerID = p.player2);

这里有个例子。

我会把它分解成更小的小块,然后拼凑起来。首先获取alpha玩家的id:

SELECT playerID
FROM players
WHERE name = 'alpha';
下一步将是找出如何排除。我会得到所有与玩家1配对的玩家的列表。我通过选择player1为“alpha”的所有player2值和player2为“alpha”的所有player1值来实现这一点,如下所示:

SELECT p.player2
FROM pairs p
JOIN(
  SELECT playerID
  FROM players
  WHERE name = 'alpha') b ON b.playerID = p.player1
UNION
SELECT p.player1
FROM pairs p
JOIN(
  SELECT playerID
  FROM players
  WHERE name = 'alpha') b ON b.playerID = p.player2;
一旦你做到了这一点,剩下的唯一一步就是从玩家那里拉,玩家1不是阿尔法,2不在上面的列表中:

SELECT *
FROM players
WHERE playerID NOT IN(
  SELECT playerID
  FROM players
  WHERE name = 'alpha') 
AND playerID NOT IN(
  SELECT p.player2
  FROM pairs p
  JOIN(
    SELECT playerID
    FROM players
    WHERE name = 'alpha') b ON b.playerID = p.player1
  UNION
  SELECT p.player1
  FROM pairs p
  JOIN(
    SELECT playerID
    FROM players
    WHERE name = 'alpha') b ON b.playerID = p.player2);

示例。

替代解决方案,不使用NOT IN

方法:所有用户-所有现有对手

即使所有现有对手都为空,这也有效

SELECT p.* FROM players p
LEFT JOIN (
    SELECT CASE
            WHEN (player1 = 1) THEN player2
            WHEN (player2 = 1) THEN player1
        END AS opponentID
    FROM pairs) existingOpponents
ON (p.playerID = existingOpponents.opponentID)
WHERE (existingOpponents.opponentID IS NULL) AND 
    (p.playerID != 1);

替代解决方案,不使用NOT IN

方法:所有用户-所有现有对手

即使所有现有对手都为空,这也有效

SELECT p.* FROM players p
LEFT JOIN (
    SELECT CASE
            WHEN (player1 = 1) THEN player2
            WHEN (player2 = 1) THEN player1
        END AS opponentID
    FROM pairs) existingOpponents
ON (p.playerID = existingOpponents.opponentID)
WHERE (existingOpponents.opponentID IS NULL) AND 
    (p.playerID != 1);


确保结果不会返回Andy@Drew:留给学生做练习;。。。例如,您可以执行join而不是subselect,并将and player.id!=joined_table.id请确保结果不返回Andy@Drew:留给学生做练习;。。。例如,您可以执行join而不是subselect,并将and player.id!=joined_table.I你还在努力解决这个问题吗?没有。我更喜欢在编辑中使用我的解决方案,而不是答案,因为我不在编辑中使用NOT。但我真的很感激为下面的答案所做的努力。谢谢,伙计,它起作用了!您可以随时回答自己的问题并接受它,这可能对未来的读者更有用,因为他们会将您的编辑误认为是问题的一部分而不是解决方案。如果答案填补了一些空白,使您能够解决问题,至少你可以给他们一个投票,因为他们花时间和精力帮助你,结果却没有得到任何回报,因为你不喜欢他们的答案。同样,不要编辑你的帖子来包含答案。相反,将其作为答案发布。你也可以投票并引用任何有助于你解决问题的答案/评论。我已将帖子回滚以排除已编辑的答案。请随意将其作为实际答案发布。您仍在努力解决此问题吗?不。不知何故,我更喜欢在编辑中使用我的解决方案,而不是答案,因为我不在编辑中使用NOT。但我真的很感激为下面的答案所做的努力。谢谢,伙计,它起作用了!您可以随时回答自己的问题并接受它,这可能对未来的读者更有用,因为他们会将您的编辑误认为是问题的一部分而不是解决方案。如果答案填补了一些空白,使您能够解决问题,至少你可以给他们一个投票,因为他们花时间和精力帮助你,结果却没有得到任何回报,因为你不喜欢他们的答案。同样,不要编辑你的帖子来包含答案。相反,将其作为答案发布。你也可以投票并引用任何有助于你解决问题的答案/评论。我已将帖子回滚以排除已编辑的答案。如果一个新球员从来没有和任何人打过球,我想这个球员不会出现在结果集中,但应该出现在结果集中,那会发生什么呢?不过我还是很喜欢这种方法。我修改过的版本在所有情况下都有效,包括你提到的场景。如果一个新玩家从来没有玩过任何人,会发生什么?我想这个玩家不会出现在结果中
不是,但应该?不过,我确实喜欢这种方法。我修改过的版本在所有情况下都有效,包括您提到的场景。