将sql查询输出到" for-each"中的新sql。风格

时间:2017-07-17 18:14:10

标签: sql sql-server tsql

我正在尝试进行嵌套查询,我遇到了一些麻烦。我有两个表(简化了这个问题)有玩家信息,另一个有团队信息。我的最终目标是找到不止一支球队的球员,然后打印出他们所在的球队。

我使用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);

enter image description here

到目前为止,我已成功找到多个球队的所有球员

-- 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;

find duplicates result

我还编写了示例代码来判断玩家属于哪个团队。如您所见,我已明确搜索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
;

resolve names to teams

最终我的目标是做一个嵌套查询,其中我对多个团队的第一个玩家查询的输出将是我的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),如下面红色所示

current incorrect sql output

我想要的是类似于"对于每个"风格循环。我们搜索从上一个查询返回的 EACH 玩家的团队,而不是搜索从上一个查询返回的 ANY 玩家团队。您可以在下面看到我的目标输出(绿色)

desired SQL ouput

2 个答案:

答案 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;