populate a weeks worth of data from daily data

  • Paul Manning (9/3/2008)


    Thanks Michael Valentine Jones, I can't say I understand it but that worked perfectly!! 😀

    The basic algorithm is to find the difference in days from the earliest possible SQL Server Sunday, 1753-01-07, divide that by 7, multiply that by 7 to find the Sunday that starts the week, and then add 6 days to that to find the last day of the week. -53684 just represents 1753-01-07.

    You may find these links of interest.

    Start of Week Function:

    http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=47307

    End of Week Function:

    http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=64760

    Links to many other datetime scripts here:

    Date/Time Info and Script Links

    http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=64762

  • With a little less inline code, the query would look like this:set DateFirst 1; -- Set first day of week to Monday

    select dbo.WeekBegins( SalesDate ) as WeekOf, Line, Count(*) as LineCount, Sum( Cost ) as LineCost

    from #Daily

    group by dbo.WeekBegins( SalesDate ), Line

    order by dbo.WeekBegins( SalesDate ), Line;

    The output for the first week is this:WeekOf Line LineCount LineCost

    2008-06-30 00:00:00 8241 4 1.12

    2008-06-30 00:00:00 19292 4 5.36

    2008-06-30 00:00:00 28213 4 5.36

    2008-06-30 00:00:00 28960 4 0.92

    2008-06-30 00:00:00 38528 4 4.24

    2008-06-30 00:00:00 46734 4 3.24

    2008-06-30 00:00:00 72376 4 5.52

    2008-06-30 00:00:00 88201 4 2.72

    2008-06-30 00:00:00 88202 4 0.68

    2008-06-30 00:00:00 88249 4 1.44

    2008-06-30 00:00:00 88256 4 2.20

    2008-06-30 00:00:00 88263 4 2.80

    2008-06-30 00:00:00 98661 4 4.76Here is the WeekBegins function:/*

    Author:

    Tomm Carr

    Create date:

    10/25/2007

    Description:

    Returns the date of the first day of the week independent of the DATEFIRST setting.

    For any date passed in, this returns the date of the preceding Sunday (or whatever day

    is defined at the start of the week). If the date passed in is already Sunday, the same

    date is returned (except that the time portion has been truncated).

    */

    ALTER function [dbo].[WeekBegins](

    @pDate datetime

    )

    returns smalldatetime

    as begin

    declare @Result smalldatetime;

    set @Result = DateAdd( dd, DateDiff( dd, 0, @pDate ), 0 );

    set @Result = DateAdd( dd, 1 - DatePart( dw, @Result ), @Result );

    return @Result;

    end

    go

    I had first thought of just using a week count for grouping, such as "DateDiff( ww, 0, SalesDate )". I tried that and it works fine if the first day of the week is Sunday. DateDiff apparently is not sensitive to the setting of DATEFIRST.

    Tomm Carr
    --
    Version Normal Form -- http://groups.google.com/group/vrdbms

  • Tomm,

    THe beauty of the solution posted by Michael is it does not depend on DATEFIRST settings.

    Moreover, it allows to set required "datefirst" as a parameter.

    So, what's the point to go for the "second best" solution?

    _____________
    Code for TallyGenerator

  • Oops! Sorry...a little late to the game I guess.

    Well here's one way to create a calendar that I believe I got from this site:

    with mycte as

    (

    select cast('2007-07-31' as datetime) DateValue

    union all

    select DateValue + 1

    from mycte

    where DateValue + 1 < '2007-08-31' -- increase this for a bigger range

    )

    select DateValue

    , datepart(dy, DateValue) [day of year]

    , datename(dw, DateValue) [day]

    , datepart(dw, DateValue-1) [day of week]

    , datepart(dd, DateValue) [day of month]

    , datepart(ww, DateValue) [week]

    , datepart(mm, DateValue) [month]

    , datename(mm, DateValue) [month]

    , datepart(qq, DateValue) [quarter]

    , datepart(yy, DateValue) [year]

    , datepart(HH, DateValue) [HOUR]

    , datepart(MI, DateValue) [MIN]

    , datepart(SS, DateValue) [SEC]

    , datepart(MS, DateValue) [MILLISECOND]

    from mycte

    OPTION (MAXRECURSION 0)

  • Sergiy (9/3/2008)


    Tomm,

    THe beauty of the solution posted by Michael is it does not depend on DATEFIRST settings.

    Moreover, it allows to set required "datefirst" as a parameter.

    So, what's the point to go for the "second best" solution?

    I'm a bit confused. I went back and reread the original post to refresh my memory. Sure enough, the end of the week is specified as Sunday:

    weekly contains a summary of daily data for each week, by 'productnumber' (weekending Sunday).

    This would make the beginning of the week a Monday (set DATEFIRST 1).

    Micheal's solution, while I fully acknowledge its brilliance in every other way, has the week ending on Saturday hard-coded into it. Sure, it's possible to make it into a sproc and pass a DATEFIRST-type parameter into it but, as written, it ends the week on the wrong day and is unresponsive to the DATEFIRST setting.

    My solution, OTOH, does respond to the value of DATEFIRST. AAMOF, the first line is "set DATEFIRST 1" so the correct result set will be generated. OP can build his upsert statement around the code as written and get the result he wanted. I fail to see how this is "second best."

    Tomm Carr
    --
    Version Normal Form -- http://groups.google.com/group/vrdbms

  • I'm a bit confused. I went back and reread the original post to refresh my memory. Sure enough, the end of the week is specified as Sunday:

    weekly contains a summary of daily data for each week, by 'productnumber' (weekending Sunday).

    This would make the beginning of the week a Monday (set DATEFIRST 1).

    Micheal's solution, while I fully acknowledge its brilliance in every other way, has the week ending on Saturday hard-coded into it. Sure, it's possible to make it into a sproc and pass a DATEFIRST-type parameter into it but, as written, it ends the week on the wrong day and is unresponsive to the DATEFIRST setting.

    My solution, OTOH, does respond to the value of DATEFIRST. AAMOF, the first line is "set DATEFIRST 1" so the correct result set will be generated. OP can build his upsert statement around the code as written and get the result he wanted. I fail to see how this is "second best."

    Later the OP seemed to say that the last day of the week could be Saturday.

    Paul Manning (9/2/2008)


    I've no problem with creating a view for this but there must be a way of specifying the weekending day of week to be Saturday and using that date as the grouping?

    So either mine or Michael's solultions will work.

  • ggraber (9/4/2008)


    Later the OP seemed to say that the last day of the week could be Saturday.

    Paul Manning (9/2/2008)


    I've no problem with creating a view for this but there must be a way of specifying the weekending day of week to be Saturday and using that date as the grouping?

    So we seem to have a case of "OP confusion" or the dreaded "wandering specifications."

    So either mine or Michael's solultions will work.

    Actually, all three will work, though mine does respond to changes in DATEFIRST setting. However, probably 99.9% of all date-related code is DATEFIRST agnostic. In fact, the only time I have ever changed the setting is, like in my solution, for testing purposes and only then because I thought the user had a setting other than the default. I have never seen it in production code. So being responsive to DATEFIRST settings doesn't seem to be really big in the "must have" section. 😉

    Tomm Carr
    --
    Version Normal Form -- http://groups.google.com/group/vrdbms

  • My solution was specifically meant to be NOT responsive to the setting of DATEFIRST.

    I posted the link in one of my prior posts that has a function for the start of week. It does not use the DATEFIRST setting; you just pass the start day of the week that you want in an input parameter to the function.

    Start of Week Function:

    http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=47307

    If you prefer to have the logic directly in your query, instead of in a function call, you can just do it this way for any day of the week that you want to start the week with.

    -- Demo query for Start of Week

    select

    a.DATE,

    Sun = dateadd(dd,(datediff(dd,-53684,a.DATE)/7)*7,-53684),

    Mon = dateadd(dd,(datediff(dd,-53690,a.DATE)/7)*7,-53690),

    Tue = dateadd(dd,(datediff(dd,-53689,a.DATE)/7)*7,-53689),

    Wed = dateadd(dd,(datediff(dd,-53688,a.DATE)/7)*7,-53688),

    Thu = dateadd(dd,(datediff(dd,-53687,a.DATE)/7)*7,-53687),

    Fri = dateadd(dd,(datediff(dd,-53686,a.DATE)/7)*7,-53686),

    Sat = dateadd(dd,(datediff(dd,-53685,a.DATE)/7)*7,-53685)

    from

    MyTable a

  • Michael Valentine Jones (9/4/2008)


    My solution was specifically meant to be NOT responsive to the setting of DATEFIRST.

    Why? The purpose of DATEFIRST is to allow your functions and procedures to react to changes without having to be rewritten.

    I posted the link in one of my prior posts that has a function for the start of week. It does not use the DATEFIRST setting; you just pass the start day of the week that you want in an input parameter to the function.

    Start of Week Function:

    http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=47307

    Again, why? DATEFIRST is a universal "parameter" that lets every function and proc (including system functions like DatePart) know where you want the week to start and to perform the calculations accordingly. Why design your code to ignore DATEFIRST and have to be told at every invocation what the expected first day of the week is?

    There could well be the day when suddenly all such code starts returning wrong answers! The DBA informs you, "Oh, didn't you get the memo? We've changed the start of the week from Sunday to Monday. I adjusted DATEFIRST accordingly..." Now you have to go through all your code and look for that blankity-blank parameter and change the value. Hope you don't miss any.

    If one develops code that works with week boundaries, it must respond to changes in DATEFIRST settings. To ignore it is poor design.

    And there is no reason to ignore it. Using DatePart in the calculation is the simplest way to ensure the DATEFIRST setting will be accounted for. Just subtract the DatePart of the date from 7 and add that many days back to the date.return DateAdd( dd, 7 - DatePart( dw, @Date ), @Date )gets you the end of the week. Change the 7 to a 1 and get the start of the week. You can add code to truncate the time part and it will still be simple, direct, and if the DBA ever changes the setting of DATEFIRST, you won't be bothered in the slightest.

    Tomm Carr
    --
    Version Normal Form -- http://groups.google.com/group/vrdbms

  • Tomm Carr (9/5/2008)


    Michael Valentine Jones (9/4/2008)


    My solution was specifically meant to be NOT responsive to the setting of DATEFIRST.

    Why? The purpose of DATEFIRST is to allow your functions and procedures to react to changes without having to be rewritten.

    I posted the link in one of my prior posts that has a function for the start of week. It does not use the DATEFIRST setting; you just pass the start day of the week that you want in an input parameter to the function.

    Start of Week Function:

    http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=47307

    Again, why? DATEFIRST is a universal "parameter" that lets every function and proc (including system functions like DatePart) know where you want the week to start and to perform the calculations accordingly. Why design your code to ignore DATEFIRST and have to be told at every invocation what the expected first day of the week is?

    There could well be the day when suddenly all such code starts returning wrong answers! The DBA informs you, "Oh, didn't you get the memo? We've changed the start of the week from Sunday to Monday. I adjusted DATEFIRST accordingly..." Now you have to go through all your code and look for that blankity-blank parameter and change the value. Hope you don't miss any.

    If one develops code that works with week boundaries, it must respond to changes in DATEFIRST settings. To ignore it is poor design.

    And there is no reason to ignore it. Using DatePart in the calculation is the simplest way to ensure the DATEFIRST setting will be accounted for. Just subtract the DatePart of the date from 7 and add that many days back to the date.return DateAdd( dd, 7 - DatePart( dw, @Date ), @Date )gets you the end of the week. Change the 7 to a 1 and get the start of the week. You can add code to truncate the time part and it will still be simple, direct, and if the DBA ever changes the setting of DATEFIRST, you won't be bothered in the slightest.

    You are making a bad assumption that DATEFIRST is a universal "parameter". We do outsourcing work for many different clients, so the start of the week has to match the clients, not the servers default setting for DATEFIRST. With work for many different clients being done on the same server, I need to make sure that code does what is expected. We even have the possibility of the week starting on different days on different reports for the same client, or even being differnt on different columns within a single report.

    You need to lighten up a bit on this. I really don't care if you use DATEFIRST the way you do or ignore it the way I do, but there is nothing that says that what works in your organization is something that is universal.

    I explained the way that my code works, so people are free to use it or not.

Viewing 10 posts - 16 through 24 (of 24 total)

You must be logged in to reply to this topic. Login to reply