2016-06-10 78 views
1

我一直慷慨地給一個特定問題的oracle解決方案,但一直在努力將其轉換爲SQL Server代碼。我得到沒有錯誤,但沒有結果。以下是我使用SQL Server的版本,我已經提供了一個問題鏈接,所以你可以看到我指的答案(答案是標記爲最佳答案的答案)。將Oracle代碼轉換爲SQL Server的夾具列表

這裏是鏈接:How to code a certain maths algorithm

嘗試SQL代碼:

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), 
     (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 COUNT(1) % 2 > 0 
), 
cte (home_idx, away_idx, week_number, leagueID, num_teams, num_fake) AS (
    -- Calculate 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 
    -- Generate 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 home_idx + 1 % num_teams + num_fake -1 
      END, 
     CASE away_idx 
      WHEN num_teams + num_fake - 1 
      THEN away_idx 
      ELSE 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 
) 
INSERT INTO dbo.Fixture 
-- Join the cte results back to the League_Teams table to convert 
-- Indexes used in calculation back to the actual team ids. 
SELECT rn, 
     week_number, 
     NULL, 
     h.id, 
     a.id, 
     c.leagueid 
FROM (
      --Keeps the results in a nice order. 
     SELECT ROW_NUMBER() OVER (ORDER BY LeagueID) 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; 

回答

1

下面的代碼可能會有所幫助。

變更進行:

移除了CTE聲明和內部CTE使用列別名列列表。還放置了一些模數計算的支架,以幫助避免燈具的重複。

WITH League_Teams 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 
    -- if this is an odd number then generate a fake team that's 0. 
    SELECT TeamID AS id, 
     LeagueID, 
     ROW_NUMBER() OVER (PARTITION BY LeagueID ORDER BY TeamID) - 1 AS idx, 
     0 AS is_fake, 
     COUNT(1) OVER (PARTITION BY LeagueID) AS num_teams, 
     (COUNT(1) OVER (PARTITION BY LeagueID) % 2) AS num_fake 
    FROM Team 

    UNION ALL 
    -- Insert a fake team if required 
    SELECT NULL, 
     LeagueID, 
     COUNT(1), 
     1, 
     COUNT(1), 
     1 
    FROM Team 
    GROUP BY LeagueID 
    HAVING COUNT(1) % 2 > 0 
), 
cte AS (
    -- Calculate round 1 games 
    SELECT 
     idx AS home_idx, 
     num_teams + num_fake - 1 - idx AS away_idx, 
     1 AS week_number, 
     LeagueID AS leagueID, 
     num_teams AS num_teams, 
     num_fake AS num_fake 
    FROM league_teams 
    WHERE 2 * idx < num_teams 

    UNION ALL 

    -- Generate 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 (home_idx + 1) % (num_teams + num_fake -1) 
     END, 

     CASE away_idx 
     WHEN num_teams + num_fake - 1 THEN away_idx 
     ELSE (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) 
) 
INSERT INTO dbo.Fixture 
-- Join the cte results back to the League_Teams table to convert 
-- Indexes used in calculation back to the actual team ids. 
SELECT rn, 
     week_number, 
     NULL, 
     h.id, 
     a.id, 
     c.leagueid 
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY LeagueID, week_number) 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; 
+0

謝謝,就是這樣 –