T SQL Заполнить временную таблицу из цикла
Есть таблица IDклиента, НомерТранзакции, Сумма, Дата
Необходимо рассчитать количество транзакций в неделю, при этом если транзакций не было должен стоять номер недели и количество транзакций 0
Выбрала для каждого клиента первую неделю, когда он совершил транзакцию, и последнюю
select КартаID,
НомерТранзакции,
DATEPART(wk, ДатаИВремяСовершенияТРанзакции)) as week_number,
max(DATEPART(wk, ДатаИВремяСовершенияТРанзакции)) as start_week,
min(DATEPART(wk, ДатаИВремяСовершенияТРанзакции) as end_week
from ng
Думаю нужно через цикл заполнить временную таблицу, в которую проставить КартаID и если в неделе не было транзакций, проставить 0. Как это сделать, подскажите пожалуйста
думала для каждого клиента i = start_week
while i<=end_week begin
isnull(count(НомерТранзакции),0)
i = i+1
end
Ответы (2 шт):
Цикл не нужен. Лучше как то так:
select "КартаID"
,"НомерТранзакции"
,COUNT() OVER(PARTITION BY "КартаID", DATEPART(wk, "ДатаИВремяСовершенияТРанзакции")) AS "Кол-во транзакций за неделю"
from ng
Пример решения. Хотелось попроще, ну как вышло Проверочные данные
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 и пр.)