在PL / SQL中实现双循环算法

时间:2017-10-08 09:50:28

标签: sql oracle algorithm plsql

我是SQL的新手,我正试图制作一张存储足球联赛时间表的表格。该表包含4列(matchID, home_team, away_team, match_date)。我有8支不同的球队,每支球队应该与其他球队进行两次比赛。比赛将持续14周(每周4场比赛)。我搜索并发现double round robin algorithm做了同样的事情,但我不确定如何在PL / SQL中编写它并生成一个表。请帮帮我。

3 个答案:

答案 0 :(得分: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脚本并使用正确的日期并运行它。

答案 1 :(得分: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 |

答案 2 :(得分: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