将Oracle代码转换为SQL Server以获取夹具列表

时间:2016-06-10 10:37:10

标签: sql sql-server oracle

我已经得到了针对特定问题的oracle解决方案,但一直在努力将其转换为SQL Server代码。我没有错误,但没有得到任何结果。下面是我使用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 个答案:

答案 0 :(得分: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;