﻿<?xml version='1.0' encoding='UTF-8'?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>SQLServerCentral / Article Discussions / Article Discussions by Author / Discuss content posted by Todd Fifield  / Calendar Tables II - The Anchor / Latest Posts</title><generator>InstantForum.NET v2.9.0</generator><description>SQLServerCentral</description><link>http://www.sqlservercentral.com/Forums/</link><webMaster>notifications@sqlservercentral.com</webMaster><lastBuildDate>Sun, 19 May 2013 20:43:35 GMT</lastBuildDate><ttl>20</ttl><item><title>RE: Calendar Tables II - The Anchor</title><link>http://www.sqlservercentral.com/Forums/Topic969435-2740-1.aspx</link><description>Almost forgot... I love the idea of having the NextDay column in there because it makes it so easy to join on dates with times while still being SARGable in the Joins and Predicates. ;-)</description><pubDate>Sat, 04 Jun 2011 13:25:28 GMT</pubDate><dc:creator>Jeff Moden</dc:creator></item><item><title>RE: Calendar Tables II - The Anchor</title><link>http://www.sqlservercentral.com/Forums/Topic969435-2740-1.aspx</link><description>[quote][b]Knut Boehnert (8/16/2010)[/b][hr]Nearly excellent.Two things that made it only good for me is the "typical" fact that the date calculation works only for the US (and Canada). The other is the RBAR in the creation of the date table and the hard coded week day names.Suggestion for the date table creation below:[code]-- Set Language 'English' Set Language 'British'-- Set Language 'German'-- Set Language 'Spanish'-- Set Language 'Italian'-- Set Language 'French'---- execute sp_helplanguage -- documentation--INSERT INTO CalDay--(--    DayDate,--    NextDay,--    DayNum,--    NameOfDay--)SELECT     -- add days to anchor date, then add number of years to that calculation    DateAdd(yy, Years.YearNumber-1900, DateAdd(dd, JulianDays.Number-1, Cast('1900-01-01' As datetime))) As DayDate,    DateAdd(yy, Years.YearNumber-1900, DateAdd(dd, JulianDays.Number, Cast('1900-01-01' As datetime))) As NextDay,    Datepart(Weekday, DateAdd(yy, Years.YearNumber, DateAdd(dd, JulianDays.Number-1, Cast('1900-01-01' As datetime)))) As DayNum,    DateName(Weekday, DateAdd(yy, Years.YearNumber, DateAdd(dd, JulianDays.Number-1, Cast('1900-01-01' As datetime)))) As NameOfDayFROM dbo.Numbers JulianDays    Cross Join    (        SELECT            Number As YearNumber        FROM dbo.Numbers         WHERE Number Between 2000 And 2011    ) YearsWHERE   -- ensure that the result is actually a date (safety check)        IsDate(DateAdd(yy, Years.YearNumber-1900, DateAdd(dd, JulianDays.Number-1, Cast('1900-01-01' As datetime)))) = 1    AND -- don't generate double, one year always has 365 days        JulianDays.Number Between 1 and 365        -- add a day for years modulo by 4, but not by 100, except when modulo by 400        -- deduct 1 or 0 from 1 if modulo by 4 = if leapyear 1 - 0 = 1 --&amp;gt; one extra day        -- add 1 if modulo by 100/400 = if 1900,2100,2200 --&amp;gt; 1 - 0 + 0 - 1 --&amp;gt; no extra day        --                              if 2000, 2400, 2800 --&amp;gt; 1 - 0 + 0 - 0 --&amp;gt; one extra day        + (1 - Sign(Years.YearNumber % 4) + Sign(Years.Yearnumber % 100) - Sign(Years.YearNumber % 400))    --AND     --    Year(DateAdd(yy, Years.YearNumber-1900, DateAdd(dd, JulianDays.Number-1, Cast('1900-01-01' As datetime)))) &amp;lt; 2012Order By DayDate[/code]Certainly only works if there is dbo.Numbers around (how to at http://www.sqlservercentral.com/scripts/Advanced+SQL/62486/). The beauty of above beast is that it handles date names simply by the language that is selected and the week day numbers too.One option to clear up the code is to create an intermediate step of a temporary table that holds just the date itself, then pass this temporary table to all the functions involved and pass this result set into CalDay.Very nice and fun article to read otherwise. I really like "the boss".[/quote]Your code labels the 1st of January, 2000 as a Monday.  Check a calendar and find out that it actually occurred on a Saturday.  ;-)Also, with a Tally or Numbers table, there's just no need for the complexity nor the double hit on the Tally table.  Have a look...[code="sql"]--===== Declare some obviously-named variables and preset themDECLARE @StartYear DATETIME,        @EndYear   DATETIME; SELECT @StartYear = '2000',        @EndYear   = '2011';--===== Return the mini-date calendarWITHcteDays AS( SELECT DayDate = DATEADD(dd,t.N-1,@StartYear)   FROM dbo.Tally t --works for zero and unit based Tally tables in this case  WHERE t.N BETWEEN 1 AND DATEDIFF(dd,@StartYear,DATEADD(yy,1,@EndYear))) SELECT DayDate,        NextDay   = DATEADD(dd,1,DayDate),        DayNum    = DATEPART(dw,DayDate+@@DATEFIRST-1), --Doesn't care what DATEFIRST is set to.        NameOfDay = DATENAME(dw,DayDate)   FROM cteDays;[/code]</description><pubDate>Sat, 04 Jun 2011 13:19:19 GMT</pubDate><dc:creator>Jeff Moden</dc:creator></item><item><title>RE: Calendar Tables II - The Anchor</title><link>http://www.sqlservercentral.com/Forums/Topic969435-2740-1.aspx</link><description>[quote][b]alen teplitsky (8/18/2010)[/b][hr]nice articlei tried using it today and the only problem was that my source data had hours and minutes and it would have taken too long to figure out a way to join it properly[/quote]I know this is an old post but figured I'd show how easy that join actually is thanks to Todd's forsight in including a "NextDay" column ...[code="sql"] SELECT whatever    FROM dbo.yourtable yt    INNER JOIN dbo.Calendar c        ON yt.YourDate &amp;gt;= c.DayDate      AND yt.YourDate   &amp;lt; c.NextDay[/code]</description><pubDate>Sat, 04 Jun 2011 12:42:42 GMT</pubDate><dc:creator>Jeff Moden</dc:creator></item><item><title>RE: Calendar Tables II - The Anchor</title><link>http://www.sqlservercentral.com/Forums/Topic969435-2740-1.aspx</link><description>nice articlei tried using it today and the only problem was that my source data had hours and minutes and it would have taken too long to figure out a way to join it properly</description><pubDate>Wed, 18 Aug 2010 12:00:40 GMT</pubDate><dc:creator>alen teplitsky</dc:creator></item><item><title>RE: Calendar Tables II - The Anchor</title><link>http://www.sqlservercentral.com/Forums/Topic969435-2740-1.aspx</link><description>Thanks for sharing this with us.</description><pubDate>Mon, 16 Aug 2010 10:07:10 GMT</pubDate><dc:creator>SQLRNNR</dc:creator></item><item><title>RE: Calendar Tables II - The Anchor</title><link>http://www.sqlservercentral.com/Forums/Topic969435-2740-1.aspx</link><description>In memento of the "as compact as possible", change DayID to smalldatetime and, if necessary, start at -32768 (there are exactly 65,536 days available to the SMALLDATETIME data type).DayNum should be TINYINTNameOfDay should be VARCHAR(9)Personally, I don't agree with having NextDay in there, but that's going to depend on what kind of data you're joining to.</description><pubDate>Mon, 16 Aug 2010 09:07:47 GMT</pubDate><dc:creator>Nadrek</dc:creator></item><item><title>RE: Calendar Tables II - The Anchor</title><link>http://www.sqlservercentral.com/Forums/Topic969435-2740-1.aspx</link><description>Nearly excellent.Two things that made it only good for me is the "typical" fact that the date calculation works only for the US (and Canada). The other is the RBAR in the creation of the date table and the hard coded week day names.Suggestion for the date table creation below:[code]-- Set Language 'English' Set Language 'British'-- Set Language 'German'-- Set Language 'Spanish'-- Set Language 'Italian'-- Set Language 'French'---- execute sp_helplanguage -- documentation--INSERT INTO CalDay--(--    DayDate,--    NextDay,--    DayNum,--    NameOfDay--)SELECT     -- add days to anchor date, then add number of years to that calculation    DateAdd(yy, Years.YearNumber-1900, DateAdd(dd, JulianDays.Number-1, Cast('1900-01-01' As datetime))) As DayDate,    DateAdd(yy, Years.YearNumber-1900, DateAdd(dd, JulianDays.Number, Cast('1900-01-01' As datetime))) As NextDay,    Datepart(Weekday, DateAdd(yy, Years.YearNumber, DateAdd(dd, JulianDays.Number-1, Cast('1900-01-01' As datetime)))) As DayNum,    DateName(Weekday, DateAdd(yy, Years.YearNumber, DateAdd(dd, JulianDays.Number-1, Cast('1900-01-01' As datetime)))) As NameOfDayFROM dbo.Numbers JulianDays    Cross Join    (        SELECT            Number As YearNumber        FROM dbo.Numbers         WHERE Number Between 2000 And 2011    ) YearsWHERE   -- ensure that the result is actually a date (safety check)        IsDate(DateAdd(yy, Years.YearNumber-1900, DateAdd(dd, JulianDays.Number-1, Cast('1900-01-01' As datetime)))) = 1    AND -- don't generate double, one year always has 365 days        JulianDays.Number Between 1 and 365        -- add a day for years modulo by 4, but not by 100, except when modulo by 400        -- deduct 1 or 0 from 1 if modulo by 4 = if leapyear 1 - 0 = 1 --&amp;gt; one extra day        -- add 1 if modulo by 100/400 = if 1900,2100,2200 --&amp;gt; 1 - 0 + 0 - 1 --&amp;gt; no extra day        --                              if 2000, 2400, 2800 --&amp;gt; 1 - 0 + 0 - 0 --&amp;gt; one extra day        + (1 - Sign(Years.YearNumber % 4) + Sign(Years.Yearnumber % 100) - Sign(Years.YearNumber % 400))    --AND     --    Year(DateAdd(yy, Years.YearNumber-1900, DateAdd(dd, JulianDays.Number-1, Cast('1900-01-01' As datetime)))) &amp;lt; 2012Order By DayDate[/code]Certainly only works if there is dbo.Numbers around (how to at http://www.sqlservercentral.com/scripts/Advanced+SQL/62486/). The beauty of above beast is that it handles date names simply by the language that is selected and the week day numbers too.One option to clear up the code is to create an intermediate step of a temporary table that holds just the date itself, then pass this temporary table to all the functions involved and pass this result set into CalDay.Very nice and fun article to read otherwise. I really like "the boss".</description><pubDate>Mon, 16 Aug 2010 03:44:48 GMT</pubDate><dc:creator>Knut Boehnert</dc:creator></item><item><title>RE: Calendar Tables II - The Anchor</title><link>http://www.sqlservercentral.com/Forums/Topic969435-2740-1.aspx</link><description>Another nice example of using a date table, however when you assign the day name wouldnt you be better removing the Case statement and using the DateName(dw,&amp;lt;date&amp;gt;) function that is embeded in SQL, it removes confusion if a company doesnt use the default DATEFIRST. </description><pubDate>Mon, 16 Aug 2010 02:11:17 GMT</pubDate><dc:creator>Jason-299789</dc:creator></item><item><title>Calendar Tables II - The Anchor</title><link>http://www.sqlservercentral.com/Forums/Topic969435-2740-1.aspx</link><description>Comments posted to this topic are about the item [B]&lt;A HREF="/articles/T-SQL/70743/"&gt;Calendar Tables II - The Anchor&lt;/A&gt;[/B]</description><pubDate>Sat, 14 Aug 2010 16:57:16 GMT</pubDate><dc:creator>tfifield</dc:creator></item></channel></rss>