To Get a list of weeks, i simply run this (found online):
SET DATEFIRST 7
;with DateCTE as
(
select cast('01/01/2017' as datetime) DateValue
union all
select DateValue + 1
from DateCTE
where DateValue + 1 < '1/1/2018'
)
Select
cast(CAST(DateValue AS CHAR(11)) AS DateTime) AS [FullDate],
DATEPART(wk, DateValue) AS WeekOfYear,
DATEPART(yy, DateValue) AS CalendarYear
from DateCTE
OPTION (MAXRECURSION 0)
Obviously if I SET DATEFIRST = 1, then it gets different results.
I need to compare the days in one table, without using table variables.
This is what I'd like to achieve:
Thus I'd like to see the same 365 days that will be available in both CTE's,
I want to compare the WeekOfYear based on different DateFirsts.
I do not know how to do this effectively. I can only get it to work when I
- Create table variable 1 and run the CTE for DateFirst7
- Create table variable 2 and run the CTE for DateFirst1
This is inefficient and I am looking for a better way to do this.
There are a few things working against this
1. I dont know how to set the DateFirst inside the query. I only know how to set it before the cte.
2. I would like to use nested CTE's for this, but OPTION (MAXRECURSION 0) does not work well with nested CTE's
Is this possible – using CTE's to get required results?
Best Answer
I started with an attempt at fixing Max Vernon's answer so that it would work for any year, but ended up with two different approaches.
Approach 1. Being clever
In this method I am calculating the Sunday-based week number directly from the offset from the year's first Sunday-based week's Sunday.
A year's first Sunday-based week's Sunday can be obtained like this:
You are taking the week day of January 1 as a number of days and subtracting it from January 1, unless that date falls on Sunday, in which case you are subtracting nothing (that is what the
… % 7
is for). For Monday-based week numbers, the result of the above formula will always be a Sunday, and in this case it will be the Sunday of the first Sunday-based week of the year.Before going on to calculating Sunday-based week numbers, here is another formula for turning any date into January 1 of the same year:
Basically, take the date and subtract its DAYOFYEAR value and add one day.
Now here is a query that is using Max Vernon's set of CTEs, the above two formulae and another one to get the actual week number:
Approach 2. Using system loophole
This method is completely different in that it relies on a built-in peculiarity of the DATEDIFF function.
As you probably know, setting DATEFIRST affects the results of such functions as
DATEPART(WEEK)
andDATEPART(WEEKDAY)
. Unlike them,DATEDIFF(WEEK)
does not respect the DATEFIRST setting. It always calculates the difference as if DATEFIRST were set to 7, that is always treating weeks as Sunday-based.Knowing that, you can calculate the difference in weeks between January 1 and any date of the same year, add 1 and use that as the Sunday-based week number: