SQL - 两个字符串行之间的聚合

SQL - Aggregation between two string rows

我有以下 table,其中我有员工的交易,其中的薪水代码为 'S':

Id | Code | Amount  | Date
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

我的objective是看员工要多少天才能把工资全部花光

这是我想要的输出:

Id | Code | Amount | Month | # days when all salary drains
1  | S    | 45000  | 01    | 20
1  | S    | 45000  | 01    | 0

我已关注 并尝试关注 SQL 查询:

with cte as
     (
       select *,
        --CASE WHEN Transaction_Code in ('521', '522') then Transaction_Amt else null end as Last_V_ID
          -- find the latest 'V' ID per ArtNo
          max(case when Transaction_Code in ('521', '522') then Transaction_Amt end) 
          over (partition by INTERNAL_ACCT_NUM order by value_date) as Last_V_ID
       from [10.16.42.25].[Cross_Sell_PL].[dbo].[PL_NONPL_TRANS]
    WHERE INTERNAL_ACCT_NUM = '0103PBS8T6001'
    --order by value_date
     )
    select *,
     case when Transaction_Code in ('521', '522') then Transaction_Amt else
      ( lag(Last_V_ID,1,0) OVER (PARTITION BY INTERNAL_ACCT_NUM ORDER BY VALUE_DATE) ) 
      + Transaction_Amt end as running_balance,

       sum(case when Transaction_Amt < Last_V_ID then null else Transaction_Amt end)
       over (partition by INTERNAL_ACCT_NUM order by VALUE_DATE rows unbounded preceding)
    from cte
    order by Internal_Acct_num, value_date

问题是我无法限制代码之间的计算,也无法计算天数。

根据您的反馈修改了我的答案。

查询现在使用通用 table 表达式为工资金额和每月支付日期构建派生 table,然后是另一个派生 table编译每个日历月汇总的所有交易的列表。

将每月交易总和与薪水金额进行比较,只有当金额超过薪水阈值时,才会显示总天数(+1 包括在内,因为这包括支付薪水的日期作为第 1 天).

这样的查询显示 3 行,因为所提供的样本数据包括 12 月的工资月份,但是没有工资金额可以与 12 月的工资进行比较,因此多了 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;