涉及多个表的复杂SQL查询

涉及多个表的复杂SQL查询,sql,relational-database,Sql,Relational Database,在这个查询中,我必须列出一对球员及其playerID和playerName,他们为完全相同的球队比赛。如果一名球员为3支球队比赛,另一名球员必须为完全相同的3支球队比赛。不能少,不能多。如果有两名球员目前没有参加任何球队的比赛,他们也应该包括在内。查询应返回playerID1、playername1、playerID2、playerName2,且不重复,例如如果player1信息位于player2之前,则不应存在另一个包含player2信息的元组位于player1之前 例如,如果球员A为洋基队和

在这个查询中,我必须列出一对球员及其playerID和playerName,他们为完全相同的球队比赛。如果一名球员为3支球队比赛,另一名球员必须为完全相同的3支球队比赛。不能少,不能多。如果有两名球员目前没有参加任何球队的比赛,他们也应该包括在内。查询应返回playerID1、playername1、playerID2、playerName2,且不重复,例如如果player1信息位于player2之前,则不应存在另一个包含player2信息的元组位于player1之前

例如,如果球员A为洋基队和红袜队效力,而球员b为洋基队、红袜队和道奇队效力,我就不应该得到他们。他们都必须为洋基队,红袜队而不是其他任何人效力。现在,如果球员为同一支球队踢球,这个查询就会找到答案

 player(playerID: integer, playerName: string)
 team(teamID: integer, teamName: string, sport: string)
 plays(playerID: integer, teamID: integer)
现在我的问题是

SELECT p1.playerID, p1.playerName, p2.playerID, p2.playerName
FROM player p1, player p2, plays
WHERE p1.teamID = p2.teamID AND teamID in.....

我被困在如何处理这件事之后。关于如何解决这个问题的任何提示。谢谢你抽出时间

我认为最简单的方法是将团队连接在一起,然后根据结果加入。Postgres提供函数string_agg来聚合字符串:

select p1.playerId, p1.playerName, p2.playerId, p2.playerName
from (select p.playerId, string_agg(cast(p.TeamId as varchar(255)), ',' order by TeamId) as teams,
             pp.PlayerName
      from plays p join
           players pp
           on p.playerId = pp.playerId
      group by p.playerId
     ) p1 join
     (select p.playerId, string_agg(cast(p.TeamId as varchar(255)), ',' order by TeamId) as teams,
             pp.PlayerName
      from plays p join
           players pp
           on p.playerId = pp.playerId
      group by p.playerId
     ) p2
     on p1.playerid < p2.playerid and p1.teams = p2.teams;
这会将团队id中的两名球员加入到排序中,因此一对球员只会被考虑一次。然后,当两个玩家的所有行都具有非空的团队值时,就会出现匹配。这一点在同等条款中可能更为明确:

当两个玩家的团队不匹配时,完全外部连接将产生空值。因此,没有空值意味着所有团队都匹配。

这是对您的a的改编

使用三角形连接获得所有独特的玩家组合:

SELECT p1.playerID, p1.playerName, p2.playerID, p2.playerName
FROM player p1
INNER JOIN player p2 ON p1.playerID < p2.playerID
交换集合,减去并再次检查:

NOT EXISTS (
    SELECT teamID
    FROM plays
    WHERE playerID = p2.playerID

    EXCEPT

    SELECT teamID
    FROM plays
    WHERE playerID = p1.playerID
)
最后,将这两个条件应用于步骤1中三角形连接的结果

SELECT p1.playerID, p1.playerName, p2.playerID, p2.playerName
FROM player p1
INNER JOIN player p2 ON p1.playerID < p2.playerID
WHERE
    NOT EXISTS (
        SELECT teamID
        FROM plays
        WHERE playerID = p1.playerID

        EXCEPT

        SELECT teamID
        FROM plays
        WHERE playerID = p2.playerID
    )
AND
    NOT EXISTS (
        SELECT teamID
        FROM plays
        WHERE playerID = p2.playerID

        EXCEPT

        SELECT teamID
        FROM plays
        WHERE playerID = p1.playerID
    )
;

我们正在使用哪个数据库?对不起,我正在使用一个本地数据库,但我不知道如何将它放在这里。哪个数据库服务器?一个版本也可能是相关的,我正在使用postgres并创建了一个小数据库进行测试,但我不认为要解决这个问题,我们需要一个数据库。对不起,术语不太好。刚开始学习SQL。哪个版本的PostgreSQL?有没有不用字符串agg的方法。对不起,我对这个概念不熟悉。非常感谢,现在有道理了。唯一的问题。你说的最终加入是什么意思?事实上,这给了我为同一支球队效力的球员,而不是为同一支球队效力的球员。例如,如果球员A为洋基队和红袜队效力,而球员b为洋基队、红袜队和道奇队效力,我就不应该得到他们。他们都必须为洋基队,红袜队而不是其他任何人效力。现在这个查询找到了是否有球员为同一支球队踢球的答案。车手来自哪里?车手是所有球员对的交叉连接。这用于后续连接,以修复完全外部连接导致player2id为NULL的问题。
NOT EXISTS (
    SELECT teamID
    FROM plays
    WHERE playerID = p1.playerID

    EXCEPT

    SELECT teamID
    FROM plays
    WHERE playerID = p2.playerID
)
NOT EXISTS (
    SELECT teamID
    FROM plays
    WHERE playerID = p2.playerID

    EXCEPT

    SELECT teamID
    FROM plays
    WHERE playerID = p1.playerID
)
SELECT p1.playerID, p1.playerName, p2.playerID, p2.playerName
FROM player p1
INNER JOIN player p2 ON p1.playerID < p2.playerID
WHERE
    NOT EXISTS (
        SELECT teamID
        FROM plays
        WHERE playerID = p1.playerID

        EXCEPT

        SELECT teamID
        FROM plays
        WHERE playerID = p2.playerID
    )
AND
    NOT EXISTS (
        SELECT teamID
        FROM plays
        WHERE playerID = p2.playerID

        EXCEPT

        SELECT teamID
        FROM plays
        WHERE playerID = p1.playerID
    )
;