我已经得到了针对特定问题的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;
答案 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;