You should take a look at Microsoft's documentation on SET DATEFIRST and how you can can use that to control the behaviour of some date functions like DATEPART. You can use SET DATEFIRST
to set which day is considered the first day of the week.
For example, the below query uses that to set the first day of the week to Monday and then is able to use the DATEPART
function like normal. This paired with DENSE_RANK
to generate the week number and SUM
to calculate the rolling total generate the results you are looking for:
SET DATEFIRST 1; /*monday*/
DECLARE @BdcList_TBL TABLE(
BDC_ID numeric(18,0) NOT NULL
,BDC_CREATE_DATE date NOT NULL
);
INSERT INTO @BdcList_TBL (BDC_ID,BDC_CREATE_DATE) VALUES
(2660830,'2023-05-01')
,(2660846,'2023-05-03')
,(2678805,'2023-05-03')
,(2698805,'2023-05-04')
,(2778545,'2023-05-08')
,(2788869,'2023-05-09')
,(2798112,'2023-05-10')
,(2845531,'2023-05-15')
,(2849555,'2023-5-17');
SELECT
CONCAT(CAST(all_weeks.WEEK_NUMBER AS varchar(2)),' (',DATEPART(MONTH,all_weeks.WEEK_START),'/',DATEPART(DAY,all_weeks.WEEK_START),'-',DATEPART(MONTH,all_weeks.WEEK_END),'/',DATEPART(DAY,all_weeks.WEEK_END),')') AS [WEEK]
,all_weeks.BDC_COUNT AS ROLLING_TOTAL
FROM
/*just doing a subquery for readability in final select for formatting the dates*/
(SELECT
DENSE_RANK() OVER(ORDER BY DATEPART(WEEK,bdc_list.BDC_CREATE_DATE)) AS WEEK_NUMBER
,SUM(COUNT(1)) OVER(ORDER BY DATEPART(WEEK,bdc_list.BDC_CREATE_DATE)) AS BDC_COUNT
,DATEADD(DAY, 1 - DATEPART(WEEKDAY, MIN(bdc_list.BDC_CREATE_DATE)), CAST(MIN(bdc_list.BDC_CREATE_DATE) AS DATE)) AS WEEK_START
,DATEADD(DAY, 7 - DATEPART(WEEKDAY, MIN(bdc_list.BDC_CREATE_DATE)), CAST(MIN(bdc_list.BDC_CREATE_DATE) AS DATE)) AS WEEK_END
FROM
@BdcList_TBL AS bdc_list
GROUP BY
DATEPART(WEEK,BDC_CREATE_DATE)) AS all_weeks
ORDER BY
all_weeks.WEEK_NUMBER;
Having a custom date dimension table of sorts would certainly make it easier, but using SET DATEFIRST
makes this not much more complex than your average windowed aggregate query.
Hopefully points you in the right direction, and good luck with Epic :)