在cte中使用DATEADD()

时间:2016-06-11 08:57:58

标签: sql sql-server

我正在尝试在我的代码中使用DATEADD()函数,其中每个'week_number_我们应用一个日期,然后为下一周的数字添加7天。我遇到的问题是,如果我尝试这段代码:

DATEADD(day,(ROW_NUMBER() OVER (ORDER BY LeagueID)-1)*7,@StartFixtureWeek) AS FixtureDate

它显示每一行的新日期,并且每周分配六行(分配的行数将来可能会更改),而不是每一行说明'week_number' 1, and FixtureDate '01-09-2016',它表示第一行'week_number' 1 has FixtureDate '01-09-2016'的{​​{1}},然后'week_number1' has FixtureDate '08-09-2016'的第二行,依此类推。

应该全部为FixtureDate for 'week_number' 1 is '01-09-2016',然后是all of 'week_number' 2 is '08-09-2016,然后是'week_number' 3 is '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  

SCHEMA:

联赛:

[LeagueID] TINYINT IDENTITY(1,1) NOT NULL PRIMARY KEY, 
[LeagueName] VARCHAR(30) UNIQUE

小组:

[TeamID] TINYINT IDENTITY(1,1) NOT NULL PRIMARY KEY, 
[TeamAbbreviation] CHAR(3) UNIQUE, 
[TeamName] VARCHAR(50) UNIQUE, 
[LeagueID] TINYINT CONSTRAINT FK_Team_League FOREIGN KEY REFERENCES League(LeagueID) 

夹具:

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

DATA:

联赛:

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”表的当前输出,因为您可以看到日期不正确,因为它给出了一周的不同日期,显然它们应该是每周相同的日期。

enter image description here

2 个答案:

答案 0 :(得分:2)

我已经注释了很多额外的细节,以便让它独立运行。

/* globals Phaser:false */
// create BasicGame Class
BasicGame = {

};

// create Game function in BasicGame
BasicGame.Game = function (game) {
};

var counter = 0;
// set Game function prototype
BasicGame.Game.prototype = {

    init: function () {
        // set up input max pointers
        this.input.maxPointers = 1;
        // set up stage disable visibility change
        this.stage.disableVisibilityChange = true;
        // Set up the scaling method used by the ScaleManager
        // Valid values for scaleMode are:
        // * EXACT_FIT
        // * NO_SCALE
        // * SHOW_ALL
        // * RESIZE
        // See http://docs.phaser.io/Phaser.ScaleManager.html for full document
        this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
        // If you wish to align your game in the middle of the page then you can
        // set this value to true. It will place a re-calculated margin-left
        // pixel value onto the canvas element which is updated on orientation /
        // resizing events. It doesn't care about any other DOM element that may
        // be on the page, it literally just sets the margin.
        this.scale.pageAlignHorizontally = true;
        this.scale.pageAlignVertically = true;
        // Force the orientation in landscape or portrait.
        // * Set first to true to force landscape. 
        // * Set second to true to force portrait.
        this.scale.forceOrientation(false, true);
        // Sets the callback that will be called when the window resize event
        // occurs, or if set the parent container changes dimensions. Use this 
        // to handle responsive game layout options. Note that the callback will
        // only be called if the ScaleManager.scaleMode is set to RESIZE.
        this.scale.setResizeCallback(this.gameResized, this);
        // Set screen size automatically based on the scaleMode. This is only
        // needed if ScaleMode is not set to RESIZE.
        this.scale.updateLayout(true);
        // Re-calculate scale mode and update screen size. This only applies if
        // ScaleMode is not set to RESIZE.
        this.scale.refresh();

    },

    preload: function () {

        // Here we load the assets required for our preloader (in this case a 
        // background and a loading bar)
        this.load.image('logo', 'asset/phaser.png');
    },

    create: function () {
        // Add logo to the center of the stage
        this.logo = this.add.sprite(
            this.world.centerX, // (centerX, centerY) is the center coordination
            this.world.centerY,
            'logo');
        // Set the anchor to the center of the sprite
        this.logo.anchor.setTo(0.5, 0.5);
        this.logo.inputEnabled = true;
        this.logo.events.onInputDown.add(onClickListener, this);

        //no add text on screen to check click counter
        this.counterLabel = this.add.text(250, 16, '' , {fill:'FFFFFF'});


    },

    onClickListener: function() {
        counter++;
    this.counterLabel.text = "You clicked " + counter + " times!";
    },

    gameResized: function (width, height) {

        // This could be handy if you need to do any extra processing if the 
        // game resizes. A resize could happen if for example swapping 
        // orientation on a device or resizing the browser window. Note that 
        // this callback is only really useful if you use a ScaleMode of RESIZE 
        // and place it inside your main game state.

    }

};

返回以下内容

    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

那是你所追求的吗?

有一些拼写错误,你的例子中遗漏了我必须添加才能让它工作。这可能是你的问题,或者问题仍然可能发生在你身上,在这种情况下,我将再次提供一些细节,并在

中添加

答案 1 :(得分:1)

根据您的问题,我假设您在FixtureDate列中显示周开始的日期。如果是这种情况,那你为什么要使用ROW_NUMBER()
我认为这就是你所要求的:

DATEADD(week, week_number - 1, @StartFixtureWeek) AS FixtureDate

在您的查询代码中,它将显示如下(我已经省略了CTE和FROM子句查询):

...
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 (
...