我正在尝试进行嵌套查询,我遇到了一些麻烦。我有两个表(简化了这个问题)有玩家信息,另一个有团队信息。我的最终目标是找到不止一支球队的球员,然后打印出他们所在的球队。
我使用MS SQL Server 2014创建了sqlfiddle for testing。这是我的问题的一个小图片表示(请注意,我在数据库初始化代码中省略了此测试集中的最后一个Team):
[编辑:] sqlfiddle网站有一些问题,所以我附上了我的数据库初始化代码 [EDIT2:] sqlfiddle再次上线
CREATE TABLE Players (
userid int NOT NULL,
name char(10) NOT NULL,
CONSTRAINT [PK_Players] PRIMARY KEY CLUSTERED ([userid]),
);
INSERT INTO Players (userid,name) VALUES
(0,'Tim'),
(1,'John'),
(2,'Amy'),
(3,'Stacy'),
(4,'Craig'),
(5,'Adam'),
(6,'Rachael'),
(7,'Steve'),
(8,'Mitch');
CREATE TABLE Teams (
teamid int,
team_name char(10),
player0 int,
player1 int,
player2 int,
player3 int
CONSTRAINT [PK_Teams] PRIMARY KEY CLUSTERED ([teamid]),
-- Says that each of the Player# must correspond to a userid in the Players Table
CONSTRAINT [p0_2_player_tbl] FOREIGN KEY ([player0]) REFERENCES [dbo].[Players] ([userid]),
CONSTRAINT [p1_2_player_tbl] FOREIGN KEY ([player1]) REFERENCES [dbo].[Players] ([userid]),
CONSTRAINT [p2_2_player_tbl] FOREIGN KEY ([player2]) REFERENCES [dbo].[Players] ([userid]),
CONSTRAINT [p3_2_player_tbl] FOREIGN KEY ([player3]) REFERENCES [dbo].[Players] ([userid]),
);
INSERT INTO Teams(teamid, team_name, player0,player1,player2,player3) VALUES
(0,'green',0,1,2,3),
(1,'red' ,4,2,5,0),
(2,'blue' ,6,7,8,2),
-- (3,'black',2,2,2,NULL);
到目前为止,我已成功找到多个球队的所有球员
-- this portion in parenthesis Finds all the players on multiple teams
SELECT userid,name,count(*) as 'Num Occurances'
FROM Players
INNER JOIN Teams
ON player0=Players.Userid
OR player1=Players.Userid
OR player2=Players.Userid
OR player3=Players.Userid
GROUP BY userid,name
HAVING COUNT(*) > 1;
我还编写了示例代码来判断玩家属于哪个团队。如您所见,我已明确搜索userid = 0
/*I think I want to take the userids returned, and fnd what team
they are on*/
SELECT teamid,team_name
FROM Teams
WHERE
Player0=0 -- Instead of typing the ID directly
OR Player1=0 -- I'd like to get it from the
OR Player2=0 -- previous query
OR Player3=0
;
最终我的目标是做一个嵌套查询,其中我对多个团队的第一个玩家查询的输出将是我的teamid查询查询的输入。到目前为止我已经开发了这个,但它并没有完全符合我的喜欢
/*Issues combining the two statements, I'm not sure how to do this
I made this attempt, but It's not quite right, it list every team
and the two players, (thing of oring Player0=0 OR Player0=2
I want a list of each player and the teams they belong to*/
SELECT name,team_name
FROM Players,Teams
WHERE userid IN (
-- this portion in parenthesis Finds all the players on multiple teams
SELECT userid -- ,name,count(*) as 'Num Occurances'
FROM Players
INNER JOIN Teams
ON player0=Players.Userid
OR player1=Players.Userid
OR player2=Players.Userid
OR player3=Players.Userid
GROUP BY userid,name
HAVING COUNT(*) > 1
) GROUP BY name,team_name
ORDER BY name ASC;
然而,这给了每个团队任何重复项(想想做Player0 = 0或者player0 = 2),如下面红色所示
我想要的是类似于"对于每个"风格循环。我们搜索从上一个查询返回的 EACH 玩家的团队,而不是搜索从上一个查询返回的 ANY 玩家团队。您可以在下面看到我的目标输出(绿色)
答案 0 :(得分:2)
SQL总是提供各种可能的解决方案,但我会尽力在这里提供一个解决方案。
你的内部查询应该只是获取多个团队中的玩家(你已经完成了),外部查询可以将这些结果加入“团队”表。
SELECT name, team_name FROM (
SELECT userid, name
FROM Players
INNER JOIN Teams ON
Players.userid IN (player0, player1, player2, player3)
GROUP BY userid, name
HAVING COUNT(*) > 1
) a
INNER JOIN Teams ON userid IN (player0, player1, player2, player3)
ORDER BY Name ASC
注意:我修改了这个......
player0=Players.Userid
OR player1=Players.Userid
OR player2=Players.Userid
OR player3=Players.Userid
......对此...
Players.Userid IN (player0, player1, player2, player3)
...只是为了更清楚一点查询。
答案 1 :(得分:2)
使用COUNT OVER
计算每个用户的团队数。然后保留那些计数大于一的记录。
SELECT userid, user_name, teamid, team_name
FROM
(
SELECT
p.userid,
p.name AS user_name,
t.teamid,
t.team_name,
COUNT(*) OVER (PARTITION BY p.userid) AS num_teams
FROM Players p
JOIN Teams t ON p.Userid IN (t.player0, t.player1, t.player2, t.player3)
) counted
WHERE num_teams > 1;