Sql 在cte中使用DATEADD()
我试图在我的代码中使用DATEADD()函数,其中对于每个“周数”,我们应用一个日期,然后为下一周数添加7天。我遇到的问题是,如果我尝试以下代码:Sql 在cte中使用DATEADD(),sql,sql-server,Sql,Sql Server,我试图在我的代码中使用DATEADD()函数,其中对于每个“周数”,我们应用一个日期,然后为下一周数添加7天。我遇到的问题是,如果我尝试以下代码: DATEADD(day,(ROW_NUMBER() OVER (ORDER BY LeagueID)-1)*7,@StartFixtureWeek) AS FixtureDate 它显示每一行的新日期,并且由于每周有六行分配给它们(分配的行数将来可能会改变),因此它不是每一行说明'week\u number'1和FixtureDate'01-09-
DATEADD(day,(ROW_NUMBER() OVER (ORDER BY LeagueID)-1)*7,@StartFixtureWeek) AS FixtureDate
它显示每一行的新日期,并且由于每周有六行分配给它们(分配的行数将来可能会改变),因此它不是每一行说明'week\u number'1和FixtureDate'01-09-2016'
,而是说明'week\u number'1的第一行说明FixtureDate'01-09-2016'
,然后,第二行的“周数1”有固定日期“08-09-2016”,依此类推
“周号”1的固定日期应为“01-09-2016”,然后“周号”2的固定日期应为“08-09-2016”,然后“周号”3的固定日期应为“15-09-2016”,依此类推
如果我尝试这样做:
DATEADD(day,(ROW_NUMBER() OVER (ORDER BY LeagueID, week_number)-1)*7,@StartFixtureWeek) AS FixtureDate,
不显示任何结果
下面是我目前使用的DATEADD()函数的代码(从底部算起的第14行)。实际上,我需要它精确地处理我的“Week_number”的工作方式,而不是FixtureDate
更新:
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,
DATEADD(day,(ROW_NUMBER() OVER (ORDER BY week_number)-1)*7,@StartFixtureWeek) AS WeekNumber,
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;
select * from dbo.Fixture
where LeagueID = 1
小组:
固定装置:
[FixtureID] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
[WeekNumber] INT NOT NULL,
[FixtureDate] DATE NULL,
[HomeTeamID] TINYINT NULL,
[AwayTeamID] TINYINT NULL,
[LeagueID] TINYINT CONSTRAINT FK_Fixture_League FOREIGN KEY REFERENCES League(LeagueID)
数据:
联盟:
[LeagueID] TINYINT IDENTITY(1,1) NOT NULL PRIMARY KEY,
[LeagueName] VARCHAR(30) UNIQUE
1, 'English Premiership'
2, 'English Division 1'
小组:
1, 'BCN', 'FC Barcelona', 1
2, 'MAD', 'Real Madrid', 1
3, 'ATH', 'Athletico Madrid', 1
4, 'ESP', 'Espanyol', 1
5, 'MAN', 'Manchester United', 2
6, 'BOL', 'Bolton', 2
7, 'CHE', 'Chelsea', 2
8, 'ARS', 'Arsenal', 2
下面是“Fixture”表的当前输出,正如您所看到的,日期是不正确的,因为它给出了一个星期的不同日期,而很明显,它们每周应该是相同的日期
我已经注释掉了许多额外的细节,以使其独立工作
DECLARE @StartFixtureWeek datetime
SET @StartFixtureWeek = '2016-03-01';
WITH 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 < 10
--(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,
DATEADD(day,(ROW_NUMBER() OVER (ORDER BY --LeagueID,
week_number)-1)*7,@StartFixtureWeek) AS FixtureDate
--,
--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) t) a
这就是你想要的吗
您的示例中缺少了一些打字错误,我必须添加这些错误才能使其正常工作。这可能是您的问题,或者您仍然会遇到问题,在这种情况下,我将再次尝试在中根据您的问题添加一些详细信息。我假设在FixtureDate列中,您希望显示本周开始的日期。如果这就是为什么要使用
行数()
?我想这就是你所追求的:
DATEADD(week, week_number - 1, @StartFixtureWeek) AS FixtureDate
在您的查询代码中,它将显示如下(我已输入CTE和FROM子句query):
你能展示联盟球队的结构和内容吗,这样我就可以测试完整版本了?嗨,迈克,谢谢你的回答。这就是我想要的,如果它是一个独立的,但是如果我用我的完整代码和完整的赛程表输出它,它仍然会出现同样的问题。我已经更新了问题,包括完整的代码,table“Fixture”表的架构、数据和当前输出,以便您可以看到正在发生的情况。如果您能再次尝试,我将不胜感激,因为我相信您将知道如何解决此问题:)请显示预期结果。根据您的问题,我假设在
FixtureDate
列中,您希望显示一周开始的日期。如果是这种情况,那么为什么要使用ROW_NUMBER()?这不是你想要的“将DATEADD(week,week_number-1,@StartFixtureWeek)作为FixtureDate”吗?事实上这是正确的Alex,我没有想到,我认为我需要第行()来做这件事。你可以把它作为一个答案,我会标记它。谢谢,很高兴它起了作用!我已经发布了上述评论作为回答。
1 1 2016-03-01 00:00:00.000
2 2 2016-03-08 00:00:00.000
3 3 2016-03-15 00:00:00.000
4 4 2016-03-22 00:00:00.000
5 5 2016-03-29 00:00:00.000
6 6 2016-04-05 00:00:00.000
7 7 2016-04-12 00:00:00.000
8 8 2016-04-19 00:00:00.000
9 9 2016-04-26 00:00:00.000
10 10 2016-05-03 00:00:00.000
DATEADD(week, week_number - 1, @StartFixtureWeek) AS FixtureDate
...
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,
DATEADD(week, week_number - 1, @StartFixtureWeek) AS FixtureDate,
h.id,
a.id,
c.leagueid
FROM (
...