簡體   English   中英

如何在 Oracle SQL 19 中使用基於組的所有行填寫 null 值?

[英]How do I fill in null values with all rows based on group in Oracle SQL 19?

我在 Oracle SQL 19 中有下表:

+--------------+--------------+-------------------+------------------+-------------------+
|     Team     | Team Ranking | Team Ranking Date | Player Join Date |      Player       |
+--------------+--------------+-------------------+------------------+-------------------+
| FC Barcelona |            1 | 15-Jul-20         | 15-Jul-20        | Lionel Messi      |
| FC Barcelona |            1 | 15-Jul-20         | 15-Jul-20        | Luis Suarez       |
| FC Barcelona |            1 | 15-Jul-20         | 15-Jul-20        | Antoine Griezmann |
| FC Barcelona |            1 | 15-Jul-20         | 15-Jul-20        | Ousmane Dembele   |
| FC Barcelona |            3 | 16-Jul-20         | (null)           | (null)            |
| FC Barcelona |            5 | 17-Jul-20         | (null)           | (null)            |
| Real Madrid  |            2 | 15-Jul-20         | 15-Jul-20        | Eden Hazard       |
| Real Madrid  |            2 | 15-Jul-20         | 15-Jul-20        | Sergio Ramos      |
| Real Madrid  |            2 | 15-Jul-20         | 15-Jul-20        | Karim Benzema     |
| Real Madrid  |            2 | 15-Jul-20         | 15-Jul-20        | Gareth Bale       |
| Real Madrid  |            2 | 15-Jul-20         | 16-Jul-20        | James Rodriguez   |
| Real Madrid  |            5 | 25-Jul-20         | (null)           | (null)            |
| Real Madrid  |            2 | 28-Jul-20         | (null)           | (null)            |
+--------------+--------------+-------------------+------------------+-------------------+

我想用球隊的所有球員信息填寫上表中的 null 值。 換句話說,我希望結果如下所示:

+--------------+--------------+-------------------+------------------+-------------------+
|     Team     | Team Ranking | Team Ranking Date | Player Join Date |      Player       |
+--------------+--------------+-------------------+------------------+-------------------+
| FC Barcelona |            1 | 15-Jul-20         | 15-Jul-20        | Lionel Messi      |
| FC Barcelona |            1 | 15-Jul-20         | 15-Jul-20        | Luis Suarez       |
| FC Barcelona |            1 | 15-Jul-20         | 15-Jul-20        | Antoine Griezmann |
| FC Barcelona |            1 | 15-Jul-20         | 15-Jul-20        | Ousmane Dembele   |
| FC Barcelona |            3 | 16-Jul-20         | 15-Jul-20*       | Lionel Messi*     |
| FC Barcelona |            3 | 16-Jul-20         | 15-Jul-20*       | Luis Suarez*      |
| FC Barcelona |            3 | 16-Jul-20         | 15-Jul-20*       | Antoine Griezmann*|
| FC Barcelona |            3 | 16-Jul-20         | 15-Jul-20*       | Ousmane Dembele*  |
| FC Barcelona |            5 | 17-Jul-20         | 15-Jul-20*       | Lionel Messi*     |
| FC Barcelona |            5 | 17-Jul-20         | 15-Jul-20*       | Luis Suarez*      |
| FC Barcelona |            5 | 17-Jul-20         | 15-Jul-20*       | Antoine Griezmann*|
| FC Barcelona |            5 | 17-Jul-20         | 15-Jul-20*       | Ousmane Dembele*  |
| Real Madrid  |            2 | 15-Jul-20         | 15-Jul-20        | Eden Hazard       |
| Real Madrid  |            2 | 15-Jul-20         | 15-Jul-20        | Sergio Ramos      |
| Real Madrid  |            2 | 15-Jul-20         | 15-Jul-20        | Karim Benzema     |
| Real Madrid  |            2 | 15-Jul-20         | 15-Jul-20        | Gareth Bale       |
| Real Madrid  |            2 | 15-Jul-20         | 16-Jul-20        | James Rodriguez   |
| Real Madrid  |            5 | 25-Jul-20         | 15-Jul-20*       | Eden Hazard*      |
| Real Madrid  |            5 | 25-Jul-20         | 15-Jul-20*       | Sergio Ramos*     |
| Real Madrid  |            5 | 25-Jul-20         | 15-Jul-20*       | Karim Benzema*    |
| Real Madrid  |            5 | 25-Jul-20         | 15-Jul-20*       | Gareth Bale*      |
| Real Madrid  |            5 | 25-Jul-20         | 16-Jul-20*       | James Rodriguez*  |
| Real Madrid  |            2 | 28-Jul-20         | 15-Jul-20*       | Eden Hazard*      |
| Real Madrid  |            2 | 28-Jul-20         | 15-Jul-20*       | Sergio Ramos*     |
| Real Madrid  |            2 | 28-Jul-20         | 15-Jul-20*       | Karim Benzema*    |
| Real Madrid  |            2 | 28-Jul-20         | 15-Jul-20*       | Gareth Bale*      |
| Real Madrid  |            2 | 28-Jul-20         | 16-Jul-20*       | James Rodriguez*  |
+--------------+--------------+-------------------+------------------+-------------------+

我在上表中為填寫的值加了星標。

在這個例子中,我只展示了每個團隊的兩個排名變化。 但是一個團隊的排名可以無限次地改變。

有人可以告訴我如何在 Oracle SQL 19 中執行此操作嗎?

任何幫助將不勝感激!

為了您的方便,下面是 sql 查詢生成 Oracle 中的表:

with tbl as (
    select 'FC Barcelona' team, 1 team_ranking, to_date('7/15/2020 09:29', 'MM/DD/YYYY HH24:MI') team_ranking_date, to_date('7/15/2020 11:31', 'MM/DD/YYYY HH24:MI') player_join_date,  'Lionel Messi' player from dual union
    select 'FC Barcelona' team, 1 team_ranking, to_date('7/15/2020 09:29', 'MM/DD/YYYY HH24:MI') team_ranking_date, to_date('7/15/2020 11:31', 'MM/DD/YYYY HH24:MI') player_join_date,  'Luis Suarez' player from dual union
    select 'FC Barcelona' team, 1 team_ranking, to_date('7/15/2020 09:29', 'MM/DD/YYYY HH24:MI') team_ranking_date, to_date('7/15/2020 11:31', 'MM/DD/YYYY HH24:MI') player_join_date,  'Antoine Griezmann' player from dual union
    select 'FC Barcelona' team, 1 team_ranking, to_date('7/15/2020 09:29', 'MM/DD/YYYY HH24:MI') team_ranking_date, to_date('7/15/2020 11:31', 'MM/DD/YYYY HH24:MI') player_join_date,  'Ousmane Dembele' player from dual union
    select 'FC Barcelona' team, 3 team_ranking, to_date('7/16/2020 04:18', 'MM/DD/YYYY HH24:MI') team_ranking_date, null player_join_date,  null player from dual union
    select 'FC Barcelona' team, 5 team_ranking, to_date('7/17/2020 06:54', 'MM/DD/YYYY HH24:MI') team_ranking_date, null player_join_date,  null player from dual union
    select 'Real Madrid' team, 2 team_ranking, to_date('7/15/2020 09:29', 'MM/DD/YYYY HH24:MI') team_ranking_date, to_date('7/15/2020 11:31', 'MM/DD/YYYY HH24:MI') player_join_date,  'Eden Hazard' player from dual union
    select 'Real Madrid' team, 2 team_ranking, to_date('7/15/2020 09:29', 'MM/DD/YYYY HH24:MI') team_ranking_date, to_date('7/15/2020 11:31', 'MM/DD/YYYY HH24:MI') player_join_date,  'Sergio Ramos' player from dual union
    select 'Real Madrid' team, 2 team_ranking, to_date('7/15/2020 09:29', 'MM/DD/YYYY HH24:MI') team_ranking_date, to_date('7/15/2020 11:31', 'MM/DD/YYYY HH24:MI') player_join_date,  'Karim Benzema' player from dual union
    select 'Real Madrid' team, 2 team_ranking, to_date('7/15/2020 09:29', 'MM/DD/YYYY HH24:MI') team_ranking_date, to_date('7/15/2020 11:31', 'MM/DD/YYYY HH24:MI') player_join_date,  'Gareth Bale' player from dual union
    select 'Real Madrid' team, 2 team_ranking, to_date('7/15/2020 09:29', 'MM/DD/YYYY HH24:MI') team_ranking_date, to_date('7/16/2020 14:44', 'MM/DD/YYYY HH24:MI') player_join_date,  'James Rodriguez' player from dual union
    select 'Real Madrid' team, 5 team_ranking, to_date('7/25/2020 10:02', 'MM/DD/YYYY HH24:MI') team_ranking_date, null player_join_date,  null player from dual union
    select 'Real Madrid' team, 2 team_ranking, to_date('7/28/2020 06:13', 'MM/DD/YYYY HH24:MI') team_ranking_date, null player_join_date,  null player from dual
)
select *
from tbl
order by team, team_ranking_date, player_join_date

您需要單獨考慮帶有 null 播放器和非空播放器的集合。 直接取非空玩家的集合。 並為 rest 應用外連接和交叉連接,並通過UNION ALL組合所有結果,如下所示:

with  tbl2 as
  (    
    select * from tbl where player is not null
    union all
    select tt1.team, tt2.team_ranking, tt2.team_ranking_date, tt1.player_join_date, tt1.player
      from
      (
       (select t2.*
          from ( select * from tbl where player is null ) t1
         right join ( select * from tbl where player is not null ) t2 on t2.player = t1.player ) tt1
       cross join      
       (select t1.*
          from ( select * from tbl where player is null ) t1
         left join ( select * from tbl where player is not null ) t2 on t2.player = t1.player ) tt2
      )          
  )
 select * 
   from tbl2 
  order by team, team_ranking_date, player_join_date

如果您只有一張表(正如您在問題中所寫),您應該為 TEAMS、PLAYERS、TEAMPLAYERS 和 TEAMRANKINGS 創建表。 一旦你有了這些表,你就可以編寫一個查詢來給你所需的結果。 (您只需要創建一次表。根據需要運行查詢...)

create table teams
as
select unique team from tbl ; -- TBL: your original table

create table players 
as
select unique player from tbl where player is not null ;

-- map players <-> teams
create table teamplayers
as
select unique team, player, player_join_date 
from tbl
where player is not null ;

-- each team will have multiple rankings
create table teamrankings
as
select unique team, team_ranking, team_ranking_date
from tbl ;

-- check: 
select * from teams ;        -- 2 rows
select * from players ;      -- 9 rows
select * from teamplayers ;  -- 9 rows
select * from teamrankings ; -- 6 rows

詢問

select 
  T.team
, TR.team_ranking
, TR.team_ranking_date
, TP.player_join_date
, P.player
from teams T
  join teamplayers TP  on T.team = TP.team
  join players P       on TP.player = P.player
  join teamrankings TR on T.team = TR.team
order by T.team, TR.team_ranking_date, P.player
; 

結果

           TEAM    TEAM_RANKING    TEAM_RANKING_DATE    PLAYER_JOIN_DATE               PLAYER 
_______________ _______________ ____________________ ___________________ ____________________ 
FC Barcelona                  1 15-JUL-20            15-JUL-20           Antoine Griezmann    
FC Barcelona                  1 15-JUL-20            15-JUL-20           Lionel Messi         
FC Barcelona                  1 15-JUL-20            15-JUL-20           Luis Suarez          
FC Barcelona                  1 15-JUL-20            15-JUL-20           Ousmane Dembele      
FC Barcelona                  3 16-JUL-20            15-JUL-20           Antoine Griezmann    
FC Barcelona                  3 16-JUL-20            15-JUL-20           Lionel Messi         
FC Barcelona                  3 16-JUL-20            15-JUL-20           Luis Suarez          
FC Barcelona                  3 16-JUL-20            15-JUL-20           Ousmane Dembele      
FC Barcelona                  5 17-JUL-20            15-JUL-20           Antoine Griezmann    
FC Barcelona                  5 17-JUL-20            15-JUL-20           Lionel Messi         
FC Barcelona                  5 17-JUL-20            15-JUL-20           Luis Suarez          
FC Barcelona                  5 17-JUL-20            15-JUL-20           Ousmane Dembele      
Real Madrid                   2 15-JUL-20            15-JUL-20           Eden Hazard          
Real Madrid                   2 15-JUL-20            15-JUL-20           Gareth Bale          
Real Madrid                   2 15-JUL-20            16-JUL-20           James Rodriguez      
Real Madrid                   2 15-JUL-20            15-JUL-20           Karim Benzema        
Real Madrid                   2 15-JUL-20            15-JUL-20           Sergio Ramos         
Real Madrid                   5 25-JUL-20            15-JUL-20           Eden Hazard          
Real Madrid                   5 25-JUL-20            15-JUL-20           Gareth Bale          
Real Madrid                   5 25-JUL-20            16-JUL-20           James Rodriguez      
Real Madrid                   5 25-JUL-20            15-JUL-20           Karim Benzema        
Real Madrid                   5 25-JUL-20            15-JUL-20           Sergio Ramos         
Real Madrid                   2 28-JUL-20            15-JUL-20           Eden Hazard          
Real Madrid                   2 28-JUL-20            15-JUL-20           Gareth Bale          
Real Madrid                   2 28-JUL-20            16-JUL-20           James Rodriguez      
Real Madrid                   2 28-JUL-20            15-JUL-20           Karim Benzema        
Real Madrid                   2 28-JUL-20            15-JUL-20           Sergio Ramos  

您還應該添加一些約束,例如

-- team names must be unique
alter table teams 
add constraint teams_unique unique( team ) ;

-- player names must be unique
alter table players 
add constraint players_unique unique( player ) ;

-- allow the user to add rankings for existing teams only
alter table teamrankings
add constraint team_fkey foreign key( team ) 
references teams( team ) ;

-- (existing) players can be added to existing teams only
alter table teamplayers
add (
  constraint teamplayers_team_fkey foreign key( team )
    references teams( team )
, constraint teamplayers_player_fkey foreign key( player )
    references players( player ) 
) ;

如果您想添加更多排名,您只需插入 TEAMRANKINGS 表,並運行與之前相同的查詢(請參閱DBfiddle )。 請注意,您現在不需要插入 PLAYER_JOIN_DATE 和 PLAYER - 這是原始表的問題(即當您添加新排名時必須插入 NULL)。

insert into teamrankings( team, team_ranking, team_ranking_date )
values( 'Real Madrid', 7, sysdate ) ;

選擇

如果由於某種原因無法創建新表,您也可以使用與上述相同的查詢,但不要使用表名,而是放入我們用於創建 4 個表的查詢:

-- TBL: your original table
select 
  T.team
, TR.team_ranking
, TR.team_ranking_date
, TP.player_join_date
, P.player
from ( select unique team from tbl ) T
  join ( 
    select unique team, player, player_join_date 
    from tbl
    where player is not null 
  ) TP on T.team = TP.team
  join (
    select unique player from tbl where player is not null 
  ) P  on TP.player = P.player
  join ( 
    select unique team, team_ranking, team_ranking_date
    from tbl
  ) TR on T.team = TR.team
order by T.team, TR.team_ranking_date, P.player
;

DBfiddle 在這里

如果我理解正確,您有兩個“實體”要合並:一方面是不同球隊和排名的列表,另一方面是球員列表。

這個想法是 select 為其中每一個的不同值,然后交叉連接它們:

select *
from (select distinct team, team_ranking, team_ranking_date from tbl) t  join
     (select distinct team, player_join_date, player
      from tbl
      where player is not null
     ) p
     using (team)
order by team, team_ranking_date, player_join_date;

是一個 db<>fiddle。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM