SQL - агрегация между двумя строковыми строками - PullRequest
0 голосов
/ 01 марта 2019

У меня есть следующая таблица, в которой у меня есть транзакции сотрудника с зарплатой в виде кода '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

Моя цель - узнать, сколько дней требуется работнику, чтобы истощить всеего зарплата

Вот вывод, который я хочу:

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

проблема в том, что я не могу ограничить расчет между кодами, а также не могу рассчитывать дни.

1 Ответ

0 голосов
/ 01 марта 2019

Пересмотрел мой ответ на основе ваших отзывов.

В запросе теперь используется общее табличное выражение для построения производной таблицы для суммы заработной платы и дат за месяц, в который они выплачиваются, а затем другая производная таблица, которая составляет список всех транзакций, суммированных закалендарный месяц

Суммированные транзакции за месяц сравниваются с суммой оклада, и только в том случае, если сумма, пересекающая порог зарплаты, показывается суммированными днями (+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;
...