Пересмотрел мой ответ на основе ваших отзывов.
В запросе теперь используется общее табличное выражение для построения производной таблицы для суммы заработной платы и дат за месяц, в который они выплачиваются, а затем другая производная таблица, которая составляет список всех транзакций, суммированных закалендарный месяц
Суммированные транзакции за месяц сравниваются с суммой оклада, и только в том случае, если сумма, пересекающая порог зарплаты, показывается суммированными днями (+1 учитывается, поскольку включает день, когда зарплата выплачивается как день1).
Запрос, как таковой, показывает 3 строки, так как предоставленные данные выборки включают в себя то, что будет месяцем заработной платы за декабрь, однако нет заработной платы для сравнения с декабрем, следовательно, дополнительные 0. Надеюсь, это поможет.
declare @employee_transaction table (
Id int,
Code nvarchar(1),
Amount int,
Date Date
);
insert into @employee_transaction (id, Code, Amount, Date)
values
(1 , 'B' , 40 , '2017-01-01'),
(1 , 'S' , 45000 , '2017-01-02'),
(1 , 'D' , 30000 , '2017-01-15'),
(1 , 'B' , 15000 , '2017-01-20'),
(1 , 'S' , 45000 , '2017-02-02'),
(1 , 'B' , -20000 , '2017-02-04'),
(1 , 'B' , -10000 , '2017-02-05');
with Salaries as (Select INTERNAL_ACCT_NUM, Transaction_Code, Value_Date,
Transaction_Amt as Salary_Per_Month from #test1 e where
Transaction_Code='S'),
Deductions as (select sum(case when Transaction_Amt<0 then Transaction_Amt
else 0 end) as Amount, Max(Value_Date) as Drain_date from #TEST1 e2
where Transaction_Code <>'S' and Value_Date>(select Value_Date from #TEST1
e3 where Transaction_Code='S' and
DATEPART(month,e2.Value_Date)=DATEPART(month,e3.Value_Date)
and e3.Internal_Acct_Num=e2.Internal_Acct_Num)
group by DATEPART(month,e2.Value_Date))
select distinct s.INTERNAL_ACCT_NUM, s.Transaction_Code, s.Salary_Per_Month,
DATEPART(Month,e.Value_Date) as Month,
coalesce(DATEDIFF(Day,S.Value_Date,(select d.Drain_Date from Deductions d
where d.Amount+S.Salary_Per_Month<=0 and
DatePart(month,d.Drain_Date)=DatePart(month,e.Value_Date) and
d.drain_date>=s.value_date))+1,0)
from #TEST1 e
inner join Salaries s on e.Transaction_Code=s.Transaction_Code
and e.INTERNAL_ACCT_NUM=s.INTERNAL_ACCT_NUM and s.Value_Date>=e.Value_Date
and DATEPART(month, s.Value_Date)=DATEPART(month, e.Value_Date)
order by Month;