sql - 排除非排他性出现的值对

标签 sql oracle

这个问题很难用英语来描述,所以我会举一些例子。

我有一张名为 Games 的表。每个游戏由游戏编号和玩家组成,分别以两列表示:GameNum、PlayerNum。

我的问题是,我想选择拥有 的玩家对只有互相玩游戏,和没有其他人 .

以下是一些示例数据:

GameNum PlayerNum
1       100
1       101
2       102
2       103
3       102
3       104
4       105
4       106
5       106
5       107
6       100
6       101

我希望返回结果:
PlayerNum1 PlayerNum2
100        101

这是因为我们可以看到玩家 100 和 101 是唯一与彼此玩过游戏的玩家,而没有其他玩家。 102 也和 104 一起玩过,所以我们排除了 102 和 104。虽然 105 只和 106 玩过,但 106 也和 107 玩过,所以我们从结果中排除了玩家 105 和 106(因此是 107) .这让我们只有玩家 100 和 101。

每个 GameNum 在表中只会出现两次(即每个游戏总是只有两个玩家)。另请注意,我们不关心玩家是否一起玩过多个游戏(例如 GameNum 1 和 6)——前提是他们只玩过这些游戏。

我已经尝试使用 min/max 进行类似以下查询的操作,但我无法弄清楚如何排除与其他玩家一起玩过游戏的玩家。
SELECT *
FROM
(
    SELECT AU1.PlayerNum AS PlayerNum1, AU2.PlayerNum AS PlayerNum2
    FROM
    (
      SELECT GameNum, MIN(PlayerNum) AS PlayerNum
      FROM GAMES
      GROUP BY GameNum
      HAVING count(GameNum) = 2
    ) AU1
    INNER JOIN 
    (
      SELECT GameNum, MAX(PlayerNum) AS PlayerNum
      FROM GAMES
      GROUP BY GameNum
      HAVING count(GameNum) = 2
    ) AU2
    ON AU2.GameNum = AU1.GameNum
) T2
GROUP BY T2.PlayerNum1, T2.PlayerNum2
ORDER BY T2.PlayerNum1, T2.PlayerNum2;

非常感谢! :)

编辑:这是使用上述数据创建表的基本版本的查询:
CREATE TABLE Games
(
    GameNum int,
    PlayerNum int
);

INSERT INTO Games (GameNum, PlayerNum) VALUES (1, 100);
INSERT INTO Games (GameNum, PlayerNum) VALUES (1, 101);
INSERT INTO Games (GameNum, PlayerNum) VALUES (2, 102);
INSERT INTO Games (GameNum, PlayerNum) VALUES (2, 103);
INSERT INTO Games (GameNum, PlayerNum) VALUES (3, 102);
INSERT INTO Games (GameNum, PlayerNum) VALUES (3, 104);
INSERT INTO Games (GameNum, PlayerNum) VALUES (4, 105);
INSERT INTO Games (GameNum, PlayerNum) VALUES (4, 106);
INSERT INTO Games (GameNum, PlayerNum) VALUES (5, 106);
INSERT INTO Games (GameNum, PlayerNum) VALUES (5, 107);
INSERT INTO Games (GameNum, PlayerNum) VALUES (6, 100);
INSERT INTO Games (GameNum, PlayerNum) VALUES (6, 101);
INSERT INTO Games (GameNum, PlayerNum) VALUES (5, 107);
INSERT INTO Games (GameNum, PlayerNum) VALUES (6, 100);
INSERT INTO Games (GameNum, PlayerNum) VALUES (6, 101);

最佳答案

尝试这样的事情(mysql语法):

select distinct least(t1.p1, t2.p2), greatest(t1.p1, t2.p2)
from
(
 select p1, max(p2) as p2
 from (select min(PlayerNum) as p1, max(PlayerNum) as p2 from GAMES group by GameNum union select max(PlayerNum) as p1, min(PlayerNum) as p2 from GAMES group by GameNum) as q1
 group by q1.p1
 having count(distinct p2)=1
) as t1
,
(
 select min(p1) as p1, p2
 from (select min(PlayerNum) as p1, max(PlayerNum) as p2 from GAMES group by GameNum union select max(PlayerNum) as p1, min(PlayerNum) as p2 from GAMES group by GameNum) as q2
 group by q2.p2
 having count(distinct p1)=1
) as t2
where t1.p1=t2.p1 and t1.p2=t2.p2

http://sqlfiddle.com/#!2/4d9c4/9

大意:
  • 选择所有只与另外 1 个玩家一起玩过的玩家 1
  • 选择所有只与另外 1 个玩家一起玩过的玩家 2

  • 加入两个集合以找出只与彼此一起玩的玩家

    关于sql - 排除非排他性出现的值对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25213718/

    相关文章:

    sql - Oracle嵌套相关子查询问题

    mysql - 为什么key_len大于索引长度?

    mysql - '$1' 中的未知列 'field list'

    mysql - 使用多个表在 MySQL 中存储数据的一种更有效的方法

    mysql 计数查询给出 1

    oracle - 编译oracle表格

    sql - Oracle - 像 NUMBER 一样对 VARCHAR2 字段进行排序 - 我找到了一个解决方案,需要对此进行解释

    asp.net - 列名作为参数

    java - 使用 Spring StoredProcedure 类调用函数

    sql - Oracle PL/SQL Query Order By 问题与 Distinct