如何获得一个完全列出组成员的组?

How to get a group with exactly the group members listed?

一支足球队有 1 名或多名球员。一名球员属于一支或多支足球队。我有一份球员名单:'Bob', 'James', 'Sam' 我想知道哪支球队有这些球员。所以结果将是 Red Team,因为 Red Team 是唯一一支完全 'Bob', 'James', 'Sam' 的队伍。请保留我拥有的所有连接。我知道您可以在技术上在 members table 中完成所有操作,但为了简单起见,我只是这样构建的。

CREATE TABLE teams(
  name VARCHAR(25) PRIMARY KEY
);

CREATE TABLE players(
  name VARCHAR(25) PRIMARY KEY
);

CREATE TABLE members(
  team_name VARCHAR(25) NOT NULL,
  player_name VARCHAR(25) NOT NULL,
  CONSTRAINT FK_team_name FOREIGN KEY (team_name) REFERENCES teams(name),
  CONSTRAINT FK_player_name FOREIGN KEY (player_name) REFERENCES players(name)
);

INSERT INTO teams(name) VALUES ('Blue Team');
INSERT INTO teams(name) VALUES ('Red Team');
INSERT INTO teams(name) VALUES ('Green Team');
INSERT INTO teams(name) VALUES ('Purple Team');

INSERT INTO players(name) VALUES ('Bob');
INSERT INTO players(name) VALUES ('Sarah');
INSERT INTO players(name) VALUES ('James');
INSERT INTO players(name) VALUES ('Mike');
INSERT INTO players(name) VALUES ('Sam');

INSERT INTO members(team_name, player_name) VALUES ('Blue Team', 'Bob');
INSERT INTO members(team_name, player_name) VALUES ('Green Team', 'Bob');
INSERT INTO members(team_name, player_name) VALUES ('Green Team', 'Sam');
INSERT INTO members(team_name, player_name) VALUES ('Green Team', 'James');
INSERT INTO members(team_name, player_name) VALUES ('Green Team', 'Sarah');
INSERT INTO members(team_name, player_name) VALUES ('Red Team', 'Bob');
INSERT INTO members(team_name, player_name) VALUES ('Red Team', 'Sam');
INSERT INTO members(team_name, player_name) VALUES ('Red Team', 'James');
INSERT INTO members(team_name, player_name) VALUES ('Purple Team', 'Mike');
INSERT INTO members(team_name, player_name) VALUES ('Purple Team', 'Sam');

我的SQL声明:

SELECT DISTINCT
  t.name
FROM teams t
LEFT JOIN members m
  ON t.name = m.team_name
LEFT JOIN players p
  ON m.player_name = p.name
WHERE
  m.player_name in ('Bob', 'James', 'Sam')

您可以使用聚合和 having 子句。如果您想要 恰好 那些成员,那么您可以在 having 子句中进行过滤。以下假设团队内成员不能重复:

SELECT t.name
FROM teams t JOIN
     members m
     ON t.name = m.team_name JOIN
     players p
     ON m.player_name = p.name
GROUP BY t.name
HAVING SUM(CASE WHEN m.player_name IN ('Bob', 'James', 'Sam') THEN 1 ELSE 0 END) = 3 AND
       COUNT(*) = 3;

编辑:

另一种方法使用 LISTAGG():

SELECT t.name
FROM teams t JOIN
     members m
     ON t.name = m.team_name JOIN
     players p
     ON m.player_name = p.name
GROUP BY t.name
HAVING LISTAGG(m.player_name, ',') WITHIN GROUP (ORDER BY m.player_name) = 'Bob,James,Sam';

Here 是一个 db<>fiddle.

如果您只想传入一个参数,这会很方便。但是,名称必须按照正确的顺序进行比较。