I'm assuming your @@datefirst
corresponds to Sunday. And I'm also assuming that the year and month part of the text correspond to the starting day of the week rather than the ending day.
You could use this first expression in an update
or possibly even as a computed column, function or view. I can't remember which of the dates functions have issues with determinism because of regional settings, so there might be some limitations.
concat(
'Wk ',
right('0' + datename(day, dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date")), 2),
'-',
right('0' + datename(day, dateadd(day, -((datepart(weekday, "Date") + 5) % 7)+6, "Date")),2),
' ',
datename(month, dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date")),
' ',
datename(year, dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"))
)
Since there are two dates involved in the calculations you can't use the format()
function as readily. Here's a two-step update
that accomplishes the same thing:
update DateDimension
set WeekGroup =
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"),
'Wk dd-XX MMMM yyyy' /* leave a placeholder */
);
update DateDimension
set WeekGroup =
replace(
WeekGroup,
'XX',
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"),
'dd'
)
);
If you like nesting the expressions it can of course be done in a single step:
update DateDimension
set WeekGroup =
replace(
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"),
'Wk dd-XX MMMM yyyy' /* leave a placeholder */
),
'XX',
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"),
'dd'
)
);
The math is really not that complicated:
To find the start of a "week" for each date we want to determine how many days since the previous Monday. Monday is counted as day of week #2 (when @@datefirst
is set to Sunday) so we want to deduct two from the "regular" weekday numbering and have it wrap around to the previous week. To avoid negative numbers in the modular arithmetic just add 5 (which is congruent to -2 mod 7). That same expression is reused to compute all the various date parts.
EDIT: In a comment you've hinted that you do need to have a slightly different format for weeks that span a month (which could include years also).
This can be handled with a case
expression. Hopefully you've got the general idea and you can see where to make adjustments for the format you'd like to see applied between the two cases.
update DateDimension
set WeekGroup =
case
when month(dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date")) =
month(dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"))
then
replace(
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"),
'Wk dd-XX MMMM yyyy' /* leave a placeholder */
),
'XX',
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"),
'dd'
)
)
else
concat(
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"),
'Wk dd MMMM yyyy-'
),
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"),
'dd MMMM yyyy'
)
)
end;