Oracle在同一表上的选择查询(自我联接)

时间:2018-10-08 09:24:57

标签: oracle oracle11g

这看起来很简单,但没有得到预期的结果

我有一张有数据的表

Team_id, Player_id, Player_name Game_cd
1            100     abc        24
1            1000    xyz        24
1            588     ert        24
1            500     you        24
2            600     ops        24
2            700     dps        24
2            900     lmv        24
2            200     hmv        24

我必须写一个查询才能得到这样的结果

Home_team home_plr_id home_player away_team away_plr_id away_player
1            100       abc          2         600         ops
1            1000      xyz          2         900         lmv

我写的查询

select f1.Team_id as home_team, 
        f1.player_id as home_plr_id,
        f1.player_Name as home_player,
        f2.Team_id as away_team, 
        f2.player_id as away_plr_id,
        f2.player_Name as home_player

from game f1, game f2
where 
f1.team_id<> f2.team_id and
f1.game_cd = f2.game_cd

2 个答案:

答案 0 :(得分:1)

不清楚如何将主场球员与客场球员配对。但是只要您不关心它,以下可能就是您想要的:

WITH game_p AS (SELECT team_id, player_id, player_name, game_cd
                     , ROW_NUMBER() over (PARTITION BY team_id, game_cd ORDER BY player_id) pos
                     , dense_rank() over (PARTITION BY game_cd ORDER BY team_id) team_pos 
                  FROM game) 
SELECT NVL(f1.game_cd, f2.game_cd) AS game_cd
     , f1.Team_id as home_team
     , f1.player_id as home_plr_id
     , f1.player_Name as home_player
     , f2.Team_id as away_team
     , f2.player_id as away_plr_id
     , f2.player_Name as away_player
  FROM (SELECT * FROM game_p WHERE team_pos = 1) f1
  FULL JOIN (SELECT * FROM game_p WHERE team_pos = 2) f2
  ON f1.game_cd = f2.game_cd
  AND f1.pos = f2.pos

新列POS为每支球队的任何球员提供了将他们与另一支球队配对的位置。 新列TEAM_POS是将team_id映射到值1和2的原因,因为team_id随游戏的不同而不同。

最后执行FULL JOIN以获取最终列表。如果两队的球员人数都相同,则可以改为普通加入...

答案 1 :(得分:1)

@ Radagast81的自我联接的替代方法是pivot,在您的Oracle版本中可用:

select home_plr_id, home_plr_name,  away_plr_id, away_plr_name
  from (select game.*, 
               row_number() over (partition by team_id order by player_id) rn 
          from game)
  pivot (max(player_id) plr_id, max(player_name) plr_name 
         for team_id in (1 home, 2 away))

SQL Fiddle

玩家必须以某种方式编号(在此处用ID编号),可以用名字,空值甚至是随机数来完成。仅将它们放在同一行中才需要此编号。如果团队中的球员人数不同,Pivot也会起作用。