2017-10-08 27 views
0

我是SQL的新手,我試圖製作一張存儲足球聯賽時間表的表格。該表包含4列(matchID, home_team, away_team, match_date)。我有8支不同的球隊,每支球隊都應該對陣其他兩支球隊。比賽將持續14周(每週4場比賽)。我搜索並發現double round robin algorithm做同樣的事情,但我不知道如何寫在PL/SQL中,並生成一個表。請幫幫我。在PL/SQL中實現雙循環算法

+2

它看起來像有很多來自這個問題缺少。例如,是否有規定團隊預期在特定時間段內參加的頻率,主客場比賽是否允許順序進行,所有比賽的實際時間表是什麼(以及其他許多我確定的比賽) –

+0

請參閱https://stackoverflow.com/questions/13372232/sql-all-possible-round-robin-combinations-between-two-tables –

回答

0

SQL Fiddle

的Oracle 11g R2架構設置

CREATE TABLE matches (matchID, home_team, away_team, match_date) AS 
WITH rounds (round, home, away, num_players) AS (
    SELECT 1, 
     LEVEL, 
     num_players + 1 - LEVEL, 
     num_players 
    FROM (SELECT 8 AS num_players FROM DUAL) 
    CONNECT BY LEVEL <= num_players/2 
UNION ALL 
    SELECT round + 1, 
     CASE home 
      WHEN 1 THEN 1 
      WHEN 2 THEN num_players 
      ELSE home - 1 
     END, 
     CASE away 
      WHEN 2 THEN num_players 
      ELSE away - 1 
     END, 
     num_players 
    FROM rounds 
    WHERE round < num_players - 1 
) 
SELECT ROWNUM, 
     t.* 
FROM (
    SELECT home, 
     away, 
     DATE '2017-01-01' + (round - 1) * 7 AS match_date 
    FROM rounds 
    UNION ALL 
    SELECT away, 
     home, 
     DATE '2017-01-01' + (round + num_players - 2) * 7 
    FROM rounds 
) t; 

查詢1

SELECT * FROM matches 

Results

| MATCHID | HOME_TEAM | AWAY_TEAM |   MATCH_DATE | 
|---------|-----------|-----------|----------------------| 
|  1 |   1 |   8 | 2017-01-01T00:00:00Z | 
|  2 |   2 |   7 | 2017-01-01T00:00:00Z | 
|  3 |   3 |   6 | 2017-01-01T00:00:00Z | 
|  4 |   4 |   5 | 2017-01-01T00:00:00Z | 
|  5 |   1 |   7 | 2017-01-08T00:00:00Z | 
|  6 |   8 |   6 | 2017-01-08T00:00:00Z | 
|  7 |   2 |   5 | 2017-01-08T00:00:00Z | 
|  8 |   3 |   4 | 2017-01-08T00:00:00Z | 
|  9 |   1 |   6 | 2017-01-15T00:00:00Z | 
|  10 |   7 |   5 | 2017-01-15T00:00:00Z | 
|  11 |   8 |   4 | 2017-01-15T00:00:00Z | 
|  12 |   2 |   3 | 2017-01-15T00:00:00Z | 
|  13 |   1 |   5 | 2017-01-22T00:00:00Z | 
|  14 |   6 |   4 | 2017-01-22T00:00:00Z | 
|  15 |   7 |   3 | 2017-01-22T00:00:00Z | 
|  16 |   8 |   2 | 2017-01-22T00:00:00Z | 
|  17 |   1 |   4 | 2017-01-29T00:00:00Z | 
|  18 |   5 |   3 | 2017-01-29T00:00:00Z | 
|  19 |   6 |   2 | 2017-01-29T00:00:00Z | 
|  20 |   7 |   8 | 2017-01-29T00:00:00Z | 
|  21 |   1 |   3 | 2017-02-05T00:00:00Z | 
|  22 |   4 |   2 | 2017-02-05T00:00:00Z | 
|  23 |   5 |   8 | 2017-02-05T00:00:00Z | 
|  24 |   6 |   7 | 2017-02-05T00:00:00Z | 
|  25 |   1 |   2 | 2017-02-12T00:00:00Z | 
|  26 |   3 |   8 | 2017-02-12T00:00:00Z | 
|  27 |   4 |   7 | 2017-02-12T00:00:00Z | 
|  28 |   5 |   6 | 2017-02-12T00:00:00Z | 
|  29 |   8 |   1 | 2017-02-19T00:00:00Z | 
|  30 |   7 |   2 | 2017-02-19T00:00:00Z | 
|  31 |   6 |   3 | 2017-02-19T00:00:00Z | 
|  32 |   5 |   4 | 2017-02-19T00:00:00Z | 
|  33 |   7 |   1 | 2017-02-26T00:00:00Z | 
|  34 |   6 |   8 | 2017-02-26T00:00:00Z | 
|  35 |   5 |   2 | 2017-02-26T00:00:00Z | 
|  36 |   4 |   3 | 2017-02-26T00:00:00Z | 
|  37 |   6 |   1 | 2017-03-05T00:00:00Z | 
|  38 |   5 |   7 | 2017-03-05T00:00:00Z | 
|  39 |   4 |   8 | 2017-03-05T00:00:00Z | 
|  40 |   3 |   2 | 2017-03-05T00:00:00Z | 
|  41 |   5 |   1 | 2017-03-12T00:00:00Z | 
|  42 |   4 |   6 | 2017-03-12T00:00:00Z | 
|  43 |   3 |   7 | 2017-03-12T00:00:00Z | 
|  44 |   2 |   8 | 2017-03-12T00:00:00Z | 
|  45 |   4 |   1 | 2017-03-19T00:00:00Z | 
|  46 |   3 |   5 | 2017-03-19T00:00:00Z | 
|  47 |   2 |   6 | 2017-03-19T00:00:00Z | 
|  48 |   8 |   7 | 2017-03-19T00:00:00Z | 
|  49 |   3 |   1 | 2017-03-26T00:00:00Z | 
|  50 |   2 |   4 | 2017-03-26T00:00:00Z | 
|  51 |   8 |   5 | 2017-03-26T00:00:00Z | 
|  52 |   7 |   6 | 2017-03-26T00:00:00Z | 
|  53 |   2 |   1 | 2017-04-02T00:00:00Z | 
|  54 |   8 |   3 | 2017-04-02T00:00:00Z | 
|  55 |   7 |   4 | 2017-04-02T00:00:00Z | 
|  56 |   6 |   5 | 2017-04-02T00:00:00Z | 
0

您可以使用此查詢爲您的表生成記錄。請注意,我沒有執行任何constraints,這取決於您,而您應該是。您可以使用所有數據類型和約束條件編寫簡單的CREATE TABLE (語法,並將此查詢用於insert記錄。

match_groups產生的匹配組合

All_matches通過交換主隊和客隊重複匹配。

CREATE TABLE MATCH_SCHEDULE AS WITH TEAMS (name) AS 
    (SELECT 'TEAM1' 
    FROM DUAL 
    UNION ALL SELECT 'TEAM2' 
    FROM DUAL 
    UNION ALL SELECT 'TEAM3' 
    FROM DUAL 
    UNION ALL SELECT 'TEAM4' 
    FROM DUAL 
    UNION ALL SELECT 'TEAM5' 
    FROM DUAL 
    UNION ALL SELECT 'TEAM6' 
    FROM DUAL 
    UNION ALL SELECT 'TEAM7' 
    FROM DUAL 
    UNION ALL SELECT 'TEAM8' 
    FROM DUAL), 
match_groups AS 
    (SELECT t1.name home_team, 
      t2.name away_team 
    FROM 
    (SELECT rownum RNUM, 
        NAME 
     FROM TEAMS) t1 
    JOIN 
    (SELECT rownum RNUM, 
        NAME 
     FROM TEAMS) t2 ON t1.RNUM < t2.RNUM), 
All_matches AS 
    (SELECT home_team, 
      away_team 
    FROM match_groups 
    UNION ALL SELECT away_team home_team, 
        home_team away_team 
    FROM match_groups) 
SELECT ROWNUM matchID, 
       home_team, 
       away_team, 
       SYSDATE + ROWNUM match_date 
FROM All_matches; 

這將創建一個包含以下數據的表。

MATCH_SCHEDULE

MATCHID HOME_TEAM AWAY_TEAM  MATCH_DATE 
1  TEAM1  TEAM2   09-OCT-17 
2  TEAM1  TEAM3   10-OCT-17 
3  TEAM1  TEAM4   11-OCT-17 
4  TEAM1  TEAM5   12-OCT-17 
5  TEAM1  TEAM6   13-OCT-17 
6  TEAM1  TEAM7   14-OCT-17 
... 
... 
54  TEAM7  TEAM6   01-DEC-17 
55  TEAM8  TEAM6   02-DEC-17 
56  TEAM8  TEAM7   03-DEC-17 

注意MATCHID有隻是數字1,2,3 ....你也可以使用一個Oracle sequence的,如果你喜歡或相應更新。現在,由於您需要每週有4場比賽,因此您需要根據自己的需要構建一個adhoc update腳本並輸入正確的日期。

+0

感謝您的支持。該表已成功創建。但我有一個問題,根據循環賽算法,球隊不能進行第二場比賽,直到所有其他球隊都進行了第一場比賽。這就是爲什麼我想每週需要4場比賽,以便所有8支球隊都能完成他們的第一場比賽。看看這個http://tournamentscheduler.net/schedule/NDg2NDg0MzUzNg。 –

+0

如果它是一次性活動,您可以從excel生成更新腳本以將其更新爲正確的日期。例如:'update table SET matchdate = where home_team = TEAM3 AND away_team = TEAM1','update table SET matchdate = where home_team = TEAM5 AND away_team = TEAM7'...等等。 –

+0

是的,這很容易,但很耗時。有沒有辦法創建一個過程?如果一週內所有4場比賽的match_date保持不變,所有4場比賽都在同一天舉行,我想這會更容易。因此,每個球隊都會在一週後進行比賽。 –

0

試試這個程序。邏輯基於循環法

請注意,我使用:周而不是日期。安排特定日期的比賽需要其他信息,例如每天有多少,你每週可以有多少次比賽,等等。

該過程的輸入是逗號分隔的隊列表。如果輸入奇數,則會創建一個「DUMMY」用於循環法工作。這不會插入到表格中,但會提示您時間表。你可以用INSERT語句代替DBMS_OUTPUT聲明

create or replace 
    procedure test_schedule(p_teams in varchar2) 
    is 
     type t_teams is table of varchar2(15); 
     cursor c_teams is 
     select trim(regexp_substr(p_teams,'[^,]+', 1, level)) team 
     from dual 
     connect by regexp_substr(p_teams, '[^,]+', 1, level) is not null; 
     v_teams t_teams := t_teams(); 
     v_team_shift varchar2(60); 
     v_weeks number; 
     v_count number:=0; 
     v_date date; 
    begin 
     for r_teams in c_teams loop 
     v_count := v_count + 1; 
     v_teams.extend(); 
     v_teams(v_count) := r_teams.team; 
     end loop; 
     if mod(v_count, 2) != 0 then 
     v_count := v_count + 1; 
     v_teams.extend(); 
     v_teams(v_count) := 'DUMMAY'; 
     end if; 

     for i in 1..v_count loop 
     dbms_output.put_line(v_teams(i)); 
     end loop; 

     v_weeks := v_count - 1; 
     dbms_output.put_line('Weeks: '|| v_weeks||' Count: '||v_count); 

     for week in 1..v_weeks loop 
     for i in 1..v_count/2 loop 
      dbms_output.put_line(week||': '||v_teams(i)||' X '||v_teams(v_count-i+1)); 
      dbms_output.put_line(week+v_weeks||': '||v_teams(v_count-i+1)||' X '||v_teams(i)); 
     end loop; 
     -- shift teams 
     v_team_shift := v_teams(v_count); 
     for i in 1..v_count-2 loop 
      v_teams(v_count-i+1) := v_teams(v_count-i); 
     end loop; 
     v_teams(2) := v_team_shift; 
     end loop; 
    end; 
    /

爲了測試,我用:

begin test_schedule('TEAM A, TEAM B, TEAM C, TEAM D, TEAM E'); end; 
/

輸出:

Week Home  Away 
    1: TEAM A X DUMMAY 
    6: DUMMAY X TEAM A 
    1: TEAM B X TEAM E 
    6: TEAM E X TEAM B 
    1: TEAM C X TEAM D 
    6: TEAM D X TEAM C 
    2: TEAM A X TEAM E 
    7: TEAM E X TEAM A 
    2: DUMMAY X TEAM D 
    7: TEAM D X DUMMAY 
    2: TEAM B X TEAM C 
    7: TEAM C X TEAM B 
    3: TEAM A X TEAM D 
    8: TEAM D X TEAM A 
    3: TEAM E X TEAM C 
    8: TEAM C X TEAM E 
    3: DUMMAY X TEAM B 
    8: TEAM B X DUMMAY 
    4: TEAM A X TEAM C 
    9: TEAM C X TEAM A 
    4: TEAM D X TEAM B 
    9: TEAM B X TEAM D 
    4: TEAM E X DUMMAY 
    9: DUMMAY X TEAM E 
    5: TEAM A X TEAM B 
    10: TEAM B X TEAM A 
    5: TEAM C X DUMMAY 
    10: DUMMAY X TEAM C 
    5: TEAM D X TEAM E 
    10: TEAM E X TEAM D