这个问题难以用英语描述,所以我会给出一些例子。
我有一张名为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);
答案 0 :(得分:2)
尝试类似这样的东西(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)
with t as (
select distinct min(playernum) a, max(playernum) b
from games group by gamenum
)
select x.a PlayerNum1, x.b PlayerNum2
from t x left join t y
on not (x.a=y.a and x.b=y.b) and (y.a in (x.a,x.b) or y.b in (x.a,x.b))
where y.a is null
答案 2 :(得分:0)
这是另一种对我来说更简单的方法。对于每个玩家,列出一个字符串中的所有游戏,然后找到对多个玩家完全相同的游戏列表:
select games, listagg(PlayerNum, ',') within group (order by PlayerNum)
from (select g.PlayerNum, listagg(GameNum, ',') within group (order by GameNum) as games
from games g
group by g.PlayerNum
) gp
group by games
having count(*) > 1;
SQL小提琴是here。