如何编码某种数学算法

car*_*oks 9 sql sql-server sql-server-2012

我很慷慨地给出了这个算法来帮助我在SQL中创建一个fixture列表,但是将它作为SQL代码应用,我不知道该怎么做.有没有人可以指导我如何应用代码?

下面是我的表架构,下面是算法:

联盟:

[LeagueID] TINYINT IDENTITY(1,1) NOT NULL PRIMARY KEY, 
[LeagueName] VARCHAR(30) UNIQUE
Run Code Online (Sandbox Code Playgroud)

球队:

[TeamID] TINYINT IDENTITY(1,1) NOT NULL PRIMARY KEY, 
[TeamAbbreviation] CHAR(3) UNIQUE, 
[TeamName] VARCHAR(50) UNIQUE, 
[LeagueID] TINYINT CONSTRAINT FK_Team_League FOREIGN KEY REFERENCES League(LeagueID) 
Run Code Online (Sandbox Code Playgroud)

夹具:

[FixtureID] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
[WeekNumber] INT NOT NULL,
[FixtureDate] DATE NULL,
[HomeTeamID] TINYINT NULL,
[AwayTeamID] TINYINT NULL,
[LeagueID] TINYINT CONSTRAINT FK_Fixture_League FOREIGN KEY REFERENCES League(LeagueID)
Run Code Online (Sandbox Code Playgroud)

算法:

让我们根据N队的有序列表(对应于N-1多边形顶点+多边形中心)来翻译称为循环调度的算法l:

  • l通过从列表中对抗最后一个队伍来定义赛程,第二个队伍与前一个队伍进行比赛,等等.
    也就是说0 ? x < N,你扮演团队l[x]与团队l[N-1-x].

  • 要生成下一组灯具,请旋转N-1列表的第一个元素.
    那是l = l[1] + l[2] + ... + l[N-2] + l[0] + l[N-1]

  • 一旦你完成了全套N-1轮换,再做一次,但是交换主队和客场球队:打l[N-1-x]队伍l[x]而不是相反.

如果从数字排序列表开始,0..N-1那么在i列表中列表是:
l = [(i + 0) % (N-1)] + [(i + 1) % (N-1)] + ... + [(i + N-2) % (N-1)] + [N-1]

也就是说,固定装置是圆形的i:

  • i VS N-1
  • 对于0 < x < (N-1) / 2,(x + i) % (N-1)vs(N-1 - x + i) % (N-1)

现在有一个技巧,因为这只适用于偶数.否则,最后一支球队总是扮演(对球队i在第二轮i),而自然每轮有一支球队无法发挥.这意味着第4队比其他队队多出一场比赛.

为了解决这个问题,我们添加一个虚拟的团队,所以5支球队,我们有N = 6,而且在第二轮i:

  • ivs 5(假人队)
  • (i + 1) % 4 VS (4 + i) % 4
  • (i + 2) % 4 VS (3 + i) % 4

既然你知道这一点,你可以生成一个函数,它将根据整数给你固定装置.它应该输出以下内容:

0:0休息,1对4,2对3
轮1:1休息,2对0,3对4
轮2:2休息,3对1,4对0
轮3:3休息,4对2,0 vs 1
轮4:4休息,0比3,1比2


需要注意的是,而不是i在公式x + iN-1 - x + i你可以使用任何倍数m * i(所以x + m * iN-1 - x + m * i)只要mN-1互素.这N - 1 = 5 是素数,所以你可以使用任何m你想要的.

更新:

如下所示,首先是联盟表的测试数据,第二个是team表(按顺序匹配表模式列)

联盟:

1, 'English Premiership'
2, 'English Division 1'
Run Code Online (Sandbox Code Playgroud)

团队:

1, 'BCN', 'FC Barcelona', 1
2, 'MAD', 'Real Madrid', 1
3, 'ATH', 'Athletico Madrid', 1
4, 'ESP', 'Espanyol', 1
5, 'MAN', 'Manchester United', 2
6, 'BOL', 'Bolton', 2
7, 'CHE', 'Chelsea', 2
8, 'ARS', 'Arsenal', 2
Run Code Online (Sandbox Code Playgroud)

球队在主场和客场之间互相比赛,只能对阵同一联赛的球队(因此不同的联盟ID)

每轮比赛应该是这样的:

League 1:

Round 1- 01/05/2016:
1v4, 2v3

Round 2- 08/05/2016:
1v2, 3v4

Round 3- 15/05/2016:
3v1, 4v2

Round 4- 22/05/2016:
4v1, 3v2

Round 5- 29/05/2016:
2v1, 4v3

Round 6- 05/06/2016:
1v3, 2v4


League 2:

Round 1- 01/05/2016:
5v8, 6v7

Round 2- 08/05/2016:
5v6, 7v8

Round 3- 15/05/2016:
3v1, 4v2

Round 4- 22/05/2016:
8v5, 7v6

Round 5- 29/05/2016:
6v5, 8v7

Round 6- 05/06/2016:
5v7, 6v8
Run Code Online (Sandbox Code Playgroud)
  • 联赛号码是'LeagueID'
  • 回合数是'WeekNumber'
  • 日期是'夹具日期'
  • 主队数是'HomeTeamID'
  • 客队数是'AwayTeamID'

这应该全部插入'Fixture'表中.

MT0*_*MT0 1

另一个 Oracle 解决方案。

设置

CREATE TABLE League (
  LeagueID   INT PRIMARY KEY, 
  LeagueName VARCHAR(30) UNIQUE
);

CREATE TABLE Team (
  TeamID           INT PRIMARY KEY, 
  TeamAbbreviation CHAR(3) UNIQUE, 
  TeamName         VARCHAR(50) UNIQUE, 
  LeagueID         INT CONSTRAINT FK_Team_League REFERENCES League(LeagueID) 
);

CREATE TABLE Fixture (
  FixtureID   INT PRIMARY KEY,
  WeekNumber  INT NOT NULL,
  FixtureDate DATE NULL,
  HomeTeamID  INT NULL,
  AwayTeamID  INT NULL,
  LeagueID    INT CONSTRAINT FK_Fixture_League REFERENCES League(LeagueID)
);

INSERT INTO League VALUES ( 1, 'League 1' );
INSERT INTO League VALUES ( 2, 'League 2' );

INSERT INTO Team VALUES ( 1, 'AAA', 'Team A', 1 );
INSERT INTO Team VALUES ( 2, 'BBB', 'Team B', 1 );
INSERT INTO Team VALUES ( 3, 'CCC', 'Team C', 1 );
INSERT INTO Team VALUES ( 4, 'DDD', 'Team D', 1 );
INSERT INTO Team VALUES ( 5, 'EEE', 'Team E', 2 );
INSERT INTO Team VALUES ( 6, 'FFF', 'Team F', 2 );
INSERT INTO Team VALUES ( 7, 'GGG', 'Team G', 2 );
INSERT INTO Team VALUES ( 8, 'HHH', 'Team H', 2 );
INSERT INTO Team VALUES ( 9, 'III', 'Team I', 2 );
Run Code Online (Sandbox Code Playgroud)

插入 - 固定装置

INSERT INTO Fixture
WITH league_teams ( id, leagueid, idx, is_fake, num_teams, num_fake ) AS (
  -- Generate a unique-per-league index for each team that is between 0
  -- and the (number of teams - 1) and calculate the number of teams
  -- and if this is an odd number then generate a fake team as well.
  SELECT TeamID,
         LeagueID,
         ROW_NUMBER() OVER ( PARTITION BY LeagueID ORDER BY TeamID ) - 1,
         0,
         COUNT(1) OVER ( PARTITION BY LeagueID ),
         MOD( COUNT(1) OVER ( PARTITION BY LeagueID ), 2 )
  FROM Team
  UNION ALL
  SELECT NULL,
         LeagueID,
         COUNT(1),
         1,
         COUNT(1),
         1
  FROM   Team
  GROUP BY LeagueID
  HAVING MOD( COUNT(1), 2 ) > 0
),
cte ( home_idx, away_idx, week_number, leagueID, num_teams, num_fake ) AS (
  -- Start by calculating the round 1 games
  SELECT idx,
         num_teams + num_fake - 1 - idx,
         1,
         LeagueID,
         num_teams,
         num_fake
  FROM   league_teams
  WHERE  2 * idx < num_teams
UNION ALL
  -- Then generate the successive rounds with the two cases when the
  -- away team has the maximum index or otherwise.
  SELECT CASE away_idx
           WHEN num_teams + num_fake - 1
           THEN home_idx + 1
           ELSE MOD( home_idx + 1, num_teams + num_fake -1 )
           END,
         CASE away_idx
           WHEN num_teams + num_fake - 1
           THEN away_idx
           ELSE MOD( away_idx + 1, num_teams + num_fake - 1 )
           END,
        week_number + 1,
        LeagueID,
        num_teams,
        num_fake
  FROM  cte
  WHERE week_number < num_teams + num_fake - 1
)
-- Finally join the cte results back to the League_Teams table to convert
-- the indexes used in calculation back to the actual team ids.
SELECT rn,
       week_number,
       NULL,
       h.id,
       a.id,
       c.leagueid
FROM   (
         -- This step isn't necessary but it keeps the results in a nice order.
         SELECT ROWNUM AS rn,
                t.*
         FROM   (
           -- Duplicate the results swapping home and away.
           SELECT week_number,
                  home_idx,
                  away_idx,
                  LeagueId
           FROM   cte
           UNION ALL
           SELECT week_number + num_teams + num_fake - 1,
                  away_idx,
                  home_idx,
                  LeagueId
           FROM   cte
         ) t
       ) c
       INNER JOIN League_Teams h
       ON ( c.home_idx = h.idx AND c.leagueId = h.leagueID )
       INNER JOIN League_Teams a
       ON ( c.away_idx = a.idx AND c.leagueId = a.leagueID )
ORDER BY rn;
Run Code Online (Sandbox Code Playgroud)

输出

SELECT * FROM fixture;

 FIXTUREID WEEKNUMBER FIXTUREDATE         HOMETEAMID AWAYTEAMID   LEAGUEID
---------- ---------- ------------------- ---------- ---------- ----------
         1          1                              1          4          1 
         2          1                              2          3          1 
         3          1                              5                     2 
         4          1                              6          9          2 
         5          1                              7          8          2 
         6          2                              2          4          1 
         7          2                              3          1          1 
         8          2                              6                     2 
         9          2                              7          5          2 
        10          2                              8          9          2 
        11          3                              3          4          1 
        12          3                              1          2          1 
        13          3                              7                     2 
        14          3                              8          6          2 
        15          3                              9          5          2 
        16          4                              8                     2 
        17          4                              9          7          2 
        18          4                              5          6          2 
        19          5                              9                     2 
        20          5                              5          8          2 
        21          5                              6          7          2 
        22          4                              4          1          1 
        23          4                              3          2          1 
        24          6                                         5          2 
        25          6                              9          6          2 
        26          6                              8          7          2 
        27          5                              4          2          1 
        28          5                              1          3          1 
        29          7                                         6          2 
        30          7                              5          7          2 
        31          7                              9          8          2 
        32          6                              4          3          1 
        33          6                              2          1          1 
        34          8                                         7          2 
        35          8                              6          8          2 
        36          8                              5          9          2 
        37          9                                         8          2 
        38          9                              7          9          2 
        39          9                              6          5          2 
        40         10                                         9          2 
        41         10                              8          5          2 
        42         10                              7          6          2 
Run Code Online (Sandbox Code Playgroud)

(注意:FixtureDate因为NULL尚不清楚您希望如何生成此数据,但您应该能够获取周数并将其用作距赛季开始的偏移量以生成日期)