简体   繁体   English

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

[英]SQL - Aggregation between two string rows

I have a following table in which I have employee's transactions having salary as Code 'S' in it: 我有一张下表,其中有员工的薪水为代码“ 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

My objective is to see how many days does it take for the employee to drain all his salary 我的目标是看雇员花掉所有工资需要多少天

Here is the output I want: 这是我想要的输出:

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

I have followed this and tried following SQL query: 我已经遵循了这个,并尝试了以下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

The problem is I am not able to restrict the calculation between the code and also unable to calculate days. 问题是我无法限制代码之间的计算,也无法计算天数。

Revised my answer based on your feedback. 根据您的反馈修改了我的答案。

The query now uses a common table expression to build a derived table for the salary amount and the dates per month on which they are payed, followed by another derived table that compiles a list of all of the transactions summed per calendar month. 现在,查询使用公用表表达式为工资金额和支付日期的每月日期构建派生表,然后是另一个派生表,该派生表编译每个日历月总计的所有交易的列表。

The summed per month transactions are compared with the salaried amount and only where there is an amount that crosses the salary threshold do the summed days show (+1 is included as this includes the day the salary is paid as day 1). 将每月总交易与薪金金额进行比较,只有在金额超过工资阈值的情况下,才显示总和天数(包括+1,因为这包括支付薪水的第1天)。

The query as such shows 3 rows as the sample data provided includes what would be Decembers wage month, however there is no salaried amount to compare to from December hence the extra 0. I hope this helps. 这样的查询显示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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM