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-10 < 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 + i和N-1 - x + i你可以使用任何倍数m * i(所以x + m * i和N-1 - x + m * i)只要m与N-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)
这应该全部插入'Fixture'表中.
另一个 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尚不清楚您希望如何生成此数据,但您应该能够获取周数并将其用作距赛季开始的偏移量以生成日期)
| 归档时间: |
|
| 查看次数: |
165 次 |
| 最近记录: |