Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Cách viết mã một thuật toán toán học nhất định

Một giải pháp Oracle khác.

Thiết lập :

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 );

Chèn - Đồ đạc :

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;

Đầu ra :

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 

(Lưu ý:FixtureDateNULL vì không rõ bạn muốn số này được tạo như thế nào nhưng bạn có thể lấy số tuần và sử dụng số này làm phần bù từ đầu mùa để tạo ngày)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách xóa các bản sao khỏi một chuỗi trong SQL

  2. Vấn đề xoay vòng TSQL - tìm kiếm cách tiếp cận tốt hơn

  3. Ba thắng lợi về hiệu suất máy chủ SQL dễ dàng

  4. Tại sao lại có sự khác biệt về hiệu suất khi một hàm SQL được gọi từ ứng dụng .Net so với khi thực hiện cùng một lệnh gọi trong Management Studio

  5. Nhiều hàng thành một hàng và kết hợp SQL cột