Я пошел дальше и закодировал это в MySQL как вызов / упражнение.
С учетом таблиц:
CREATE TABLE IF NOT EXISTS Teams (
ID INT NOT NULL AUTO_INCREMENT,
Name VARCHAR(25) NOT NULL,
Class INT NOT NULL,
PRIMARY KEY ( ID ),
UNIQUE KEY UniqName ( Name )
);
И:
CREATE TABLE IF NOT EXISTS Matchups (
ID INT NOT NULL AUTO_INCREMENT,
Home VARCHAR(25) NOT NULL,
Away VARCHAR(25) NOT NULL,
Class INT DEFAULT NULL,
GroupNum INT DEFAULT NULL,
PRIMARY KEY ( ID ),
KEY Home ( Home , Away )
);
И данные:
INSERT INTO Teams (Name, CLASS)
VALUES ('Astros', 1),
('Bears', 1),
('Cubs', 1),
('Dragons', 1),
('Eagles', 1),
('Firebirds', 2),
('Giants', 2);
Тогда эта процедура:
DROP PROCEDURE IF EXISTS BuildFixtureTable;
DELIMITER //
CREATE PROCEDURE BuildFixtureTable(IN ClassNum INT)
BEGIN
DROP TABLE IF EXISTS tmpPool;
DROP TABLE IF EXISTS tmpFixture;
CREATE TEMPORARY TABLE tmpPool (
J INT NOT NULL AUTO_INCREMENT,
ID INT NOT NULL,
unpicked BIT NOT NULL DEFAULT 1
, PRIMARY KEY ( J )
);
CREATE TEMPORARY TABLE tmpFixture (
ID INT NOT NULL AUTO_INCREMENT,
HomeID INT NOT NULL,
AwayID INT NOT NULL,
GrpNum INT NOT NULL,
PRIMARY KEY ( `ID` )
);
INSERT INTO tmpPool (ID)
SELECT ID
FROM Teams
WHERE Class = ClassNum
ORDER BY ID;
SELECT COUNT(*) INTO @NumTeams FROM tmpPool;
IF @NumTeams % 2 THEN
INSERT INTO tmpPool (ID) VALUES (0);
SET @NumTeams = @NumTeams + 1;
END IF;
ALTER TABLE tmpPool CHANGE COLUMN J J INT NOT NULL
, ADD INDEX J_foo (J ASC)
, DROP PRIMARY KEY;
SET SQL_SAFE_UPDATES = 0; -- Kill bogus warnings on updates.
SET @GroupNum = 1;
WHILE @GroupNum < @NumTeams DO
REPEAT
SELECT ID INTO @Home FROM tmpPool WHERE unpicked = 1 ORDER BY J ASC LIMIT 1;
SELECT ID INTO @Away FROM tmpPool WHERE unpicked = 1 ORDER BY J DESC LIMIT 1;
INSERT INTO tmpFixture (HomeID, AwayID, GrpNum)
VALUES (@Home, @Away, @GroupNum);
UPDATE tmpPool SET unpicked = 0 WHERE ID = @Home OR ID = @Away;
SELECT COUNT(*) INTO @TeamsLeft FROM tmpPool WHERE unpicked = 1;
UNTIL @TeamsLeft < 1
END REPEAT;
SET @GroupNum = @GroupNum + 1;
UPDATE tmpPool SET unpicked = 1;
/*--- Do the "round robin" shuffle. This is the secret sauce.
*/
UPDATE tmpPool SET J = J + 1 WHERE J > 1;
UPDATE tmpPool SET J = 2 WHERE J = @NumTeams + 1;
END WHILE;
/*--- Now Update the payload table.
*/
INSERT INTO
Matchups (Home, Away, Class, GroupNum)
SELECT
IF( F.HomeID = 0, (SELECT Name FROM Teams T WHERE T.ID = F.AwayID), (SELECT Name FROM Teams T WHERE T.ID = F.HomeID) ),
IF( F.AwayID = 0 || F.HomeID = 0, '*na*', (SELECT Name FROM Teams T WHERE T.ID = F.AwayID) ),
ClassNum,
F.GrpNum
FROM
tmpFixture F
ORDER BY
F.GrpNum,
1;
END//
DELIMITER ;
Вызывается первый раз с помощью:
call BuildFixtureTable( 1 );
Создает эту таблицу:
ID Home Away Class GroupNum
1 Astros *na* 1 1
2 Bears Eagles 1 1
3 Cubs Dragons 1 1
4 Astros Eagles 1 2
5 Bears Cubs 1 2
6 Dragons *na* 1 2
7 Astros Dragons 1 3
8 Bears *na* 1 3
9 Eagles Cubs 1 3
10 Astros Cubs 1 4
11 Dragons Bears 1 4
12 Eagles *na* 1 4
13 Astros Bears 1 5
14 Cubs *na* 1 5
15 Dragons Eagles 1 5