Пример решения. Хотелось попроще, ну как вышло
Проверочные данные
create table trans(ClientId int,CardId int,TransNum int,TransSum money
,TransDateTime datetime);
insert into trans (ClientId, CardId, TransNum,TransSum,TransDateTime)
values
(1,1001,1,103.59,cast('2022-12-01 12:12:12' as datetime))
,(1,1001,11,203.59,cast('2022-12-01 22:22:22' as datetime))
,(1,1001,21,203.41,cast('2022-12-31 22:22:22' as datetime))
,(1,1001,31,303.59,cast('2022-12-31 22:22:22' as datetime))
,(1,1001,41,403.59,cast('2023-01-31 04:24:24' as datetime))
,(2,1001,11,203.59,cast('2023-02-01 22:22:22' as datetime))
,(2,1001,11,203.59,cast('2023-02-08 22:22:22' as datetime))
;
Само решение. Через рекурсию создаем необходимый список недель.
with weeks as( -- список годов*недель по максимуму диапазона дат
select 1 n,datepart(wk,minDt) wkn,datepart(yy,minDt) Yy
,minDt,maxDt
from (select min(TransDateTime)minDt,max(TransDateTime)maxDt from trans) mmd
union all
select n+1,datepart(wk,dateadd(wk,n+1,minDt)) wkn
,datepart(yy,dateadd(wk,n+1,minDt)) Yy,minDt,maxDt
from weeks where dateadd(wk,n,minDt)<=maxDt
)
,ClientsWeeks as(--умножаем Клиентов на Годы и Недели
select ClientId,w.yy,w.wkn
from (select distinct ClientId from trans ) Clients
cross join weeks w
)
,ClientsData as( -- присваиваем год и неделю каждой операции
select cw.ClientId,CardId,TransNum,TransSum,TransDateTime
,cw.yy,cw.wkn
from ClientsWeeks cw left join trans t1 on cw.yy=year(TransDateTime)
and cw.wkn=datepart(wk,TransDateTime)
)
,res as(-- просто отчет с группировкой по неделям
select ClientId,yy,wkn,sum(isnull(TransSum,0)) WeekSum
from ClientsData
group by CLientId,yy,wkn
)
select * from res
order by CLientId
Пример здесь
Если задача рассмотреть дата в пределах года, можно упростить.
Трудности с первой и последней неделей года не рассматривал. Как есть для тестовой субд. Нужно проверять по своим настройкам сервера (DATEFIRST и пр.)