Get Start and End Date from Week Number SQL Server

(An extra answer, since this method is a bit different.)

This method is about using a tally table with dates and date related stuff.

Then such calendar table can be used to lookup the year and week.

For example

Create calendar table

create table REF_Calendar (
 cal_date date primary key not null,
 cal_year smallint not null,
 cal_month tinyint not null,
 cal_day tinyint not null,
 cal_dayofyear smallint not null,
 cal_quarter tinyint not null,
 cal_weekday_abbrev char(3) not null,
 cal_iso_week tinyint,
 cal_df7_week tinyint not null,
 cal_df7_weekday tinyint not null,
 cal_df1_week tinyint,
 cal_df1_weekday tinyint,
 cal_mooncycle tinyint,
 index idx_Calendar_year_week unique (cal_year, cal_df7_week, cal_df7_weekday)
);

Fill the calendar

SET DATEFIRST 7; -- 7: week starts on sunday

declare @startdate date="2020-01-01";
declare @enddate   date="2023-01-01";

with rcte_calendar as (
  select @startdate as cal_date
  union all
  select dateadd(day, 1, cal_date)
  from rcte_calendar
  where cal_date < @enddate
)
insert into ref_calendar 
(cal_date, cal_year, cal_month, cal_day, cal_dayofyear, cal_quarter, cal_weekday_abbrev, 
 cal_df7_week, cal_df7_weekday, cal_mooncycle)
select
  cal_date
, datepart(year, cal_date) as cal_year
, datepart(month, cal_date) as cal_month
, datepart(day, cal_date) as cal_day
, datepart(dayofyear, cal_date) as cal_dayofyear
, datepart(quarter, cal_date) as cal_quarter
, lower(left(datename(weekday, cal_date), 3)) as cal_weekday_abbrev
, datepart(week, cal_date) as cal_df7_week
, datepart(weekday, cal_date) as cal_df7_weekday
, abs(1-abs(round(((14-1.0*CONVERT(int, CONVERT(nvarchar(2), cal_date, 131)))/14)
 , 1, 1)))*100 as cal_mooncycle
from rcte_calendar cte
where not exists (
        select 1 
        from ref_calendar cal
        where cal.cal_date = cte.cal_date
      )
option (maxrecursion 0);

Updating extra’s

SET DATEFIRST 1; -- 1: week starts on monday
update ref_calendar
set cal_df1_week = datepart(week, cal_date)
  , cal_df1_weekday = datepart(weekday, cal_date)
  , cal_iso_week = datepart(iso_week, cal_date)
where cal_df1_week is null
   or cal_df1_weekday is null
   or cal_iso_week is null;

Check how it looks

select top 9 * 
from ref_calendar 
where cal_mooncycle = 100
  and cal_date >= getdate()
  and cal_year <= 1 + datepart(year, current_timestamp)
order by cal_date asc;
cal_date cal_year cal_month cal_day cal_dayofyear cal_quarter cal_weekday_abbrev cal_iso_week cal_df7_week cal_df7_weekday cal_df1_week cal_df1_weekday cal_mooncycle
2021-12-17 2021 12 17 351 4 fri 50 51 6 51 5 100
2021-12-18 2021 12 18 352 4 sat 50 51 7 51 6 100
2021-12-19 2021 12 19 353 4 sun 50 52 1 51 7 100
2022-01-16 2022 1 16 16 1 sun 2 4 1 3 7 100
2022-01-17 2022 1 17 17 1 mon 3 4 2 4 1 100
2022-01-18 2022 1 18 18 1 tue 3 4 3 4 2 100
2022-02-14 2022 2 14 45 1 mon 7 8 2 8 1 100
2022-02-15 2022 2 15 46 1 tue 7 8 3 8 2 100
2022-02-16 2022 2 16 47 1 wed 7 8 4 8 3 100

Test applying the calendar to a table

DECLARE @Test TABLE (col char(7)); 
INSERT INTO @Test VALUES 
  ('2021-01'), ('2021-02')
, ('2021-48')
, ('2022-01'), ('2022-02')
;

select *
from @test t
outer apply (
  select 
    min(cal_date) as startofweek
  , max(cal_date) as endofweek
  from (values (try_cast(left(col, 4) as int),
            abs(try_cast(right(col, 2) as int))) 
  ) as val(yr, ww)
  join ref_calendar as cal
    on ((cal_year = yr and cal_df7_week = ww)
        or (ww = 1  and cal_year = yr-1 and cal_df7_week = 53) 
        or (ww = 53 and cal_year = yr+1 and cal_df7_week = 1))
) cal
col startofweek endofweek
2021-01 2020-12-27 2021-01-02
2021-02 2021-01-03 2021-01-09
2021-48 2021-11-21 2021-11-27
2022-01 2021-12-26 2022-01-01
2022-02 2022-01-02 2022-01-08

Demo on db<>fiddle here

Leave a Comment