T SQL Заполнить временную таблицу из цикла

Рейтинг: 0Ответов: 2Опубликовано: 19.01.2023

Есть таблица 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

Ответы

▲ 0

Цикл не нужен. Лучше как то так:

 select "КартаID"   
        ,"НомерТранзакции"
        ,COUNT() OVER(PARTITION BY "КартаID", DATEPART(wk, "ДатаИВремяСовершенияТРанзакции")) AS "Кол-во транзакций за неделю"
 from ng
▲ 0

Пример решения. Хотелось попроще, ну как вышло Проверочные данные

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 и пр.)