【问题标题】:MySQL query for pairsMySQL 查询对
【发布时间】:2015-10-19 15:20:33
【问题描述】:

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

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”行。我是新手,尝试了 GROUP BY、HAVING 等的各种组合。我无法让它工作。

SQL Fiddle here.

【问题讨论】:

  • 你还在努力解决这个问题吗?
  • 没有。我以某种方式更喜欢我的解决方案(在我的编辑中)而不是答案,因为我不使用“NOT IN”。但我非常感谢为以下答案所做的努力。谢谢
  • 很高兴它的工作!您始终可以回答自己的问题并接受它,这可能对未来的读者更有帮助,他们会将您的编辑误认为是问题的一部分而不是解决方案。
  • 如果答案填补了一些让你解决问题的空白,至少你可以给他们一个支持,因为他们投入了时间和精力来帮助你,只是没有得到任何代表因为你不“喜欢”他们的答案。
  • 作为McAdam331 said,请勿编辑您的帖子以包含答案。相反,将其发布为答案。您也可以投票并引用任何帮助您找出问题的答案/cmets。我已将帖子回滚以排除已编辑的答案。随意将其作为实际答案发布。

标签: mysql select join


【解决方案1】:

我会把它分解成更小的部分,然后拼凑起来。首先获取 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) 不是 alpha 和 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);

SQL Fiddle 此处为示例。

【讨论】:

    【解决方案2】:

    这样的事情应该适用于这种情况。

    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'
    
        )
    

    如果对表中的 player1 和 player 2 列改变位置,您可能必须在子查询中使用 CASE。

    【讨论】:

      【解决方案3】:

      应该这样做:

      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'
      ) 
      ;
      

      【讨论】:

      • 确保结果不返回 Andy
      • @Drew:留给学生做练习;)
      • ...例如,您可以进行联接而不是子选择,并在 where 子句中添加类似“and player.id !=joined_table.id”的内容
      【解决方案4】:

      另一种解决方案,不使用“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);
      

      【讨论】:

      • 如果新玩家从未玩过任何人(我认为该玩家不会出现在结果集中但应该出现),会发生什么情况?不过我确实喜欢这种方法。
      • 我的修改版本适用于所有情况,包括你提到的场景。
      猜你喜欢
      • 1970-01-01
      • 2021-02-26
      • 2021-06-30
      • 2019-01-01
      • 2017-03-19
      • 2011-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多