Обновите группу строк, чтобы удалить конкретную общую сумму из суммы строк SQL - PullRequest
0 голосов
/ 30 июня 2018

В примере я хочу вычесть значение Subtracted в TABLE 1 из общей суммы ValueBefore в Таблице 2, сгруппированной в GroupID. Значение вычитается из первой строки, а если остаток, то вычитается из следующей строки в группе (и так далее), пока не будет вычтена сумма.

Есть ли способ сделать это, не перебирая строки, чтобы получить остаток?

Мой стол 1:

TABLE 1 of subtracting value
GroupID    Subtracted
  1          32
  2          30

Мой стол 2:

ID   GroupID     ValueBefore     Reduction      ValueAfter   
 1     1             10            -10             0
 2     1             15            -15             0 
 3     1              5             -5             0 
 4     1              5             -2             3
 5     2             40            -30            10
 6     2             30              0            30

Ответы [ 2 ]

0 голосов
/ 30 июня 2018

Я бы использовал кумулятивную сумму и несколько сравнительных сравнений:

select t2.*,
       (case when t2.running_value - t2.valuebefore < t1.subtracted
             then 0
             when t2.running_value < t1.subtracted
             then t2.running_value - t1.subtracted
             else t2.valuebefore
        end) as reduction,
       (case when t2.running_value < t1.subtracted then 0
             else t2.running_value - t1.subtracted
        end) as ValueAfter
from (select t2.*,
             sum(valuebefore) over (partition by groupid order by id) as running_value
      from t2
     ) t2 join
     t1
     on t2.groupid = t1.groupid;
0 голосов
/ 30 июня 2018

Один метод заключается в использовании LEFT JOIN для вычисления промежуточного итога ValueBefore.

Этот запрос:

SELECT t2.ID, t2.GroupID, t2.ValueBefore, r.ValueBefore AS rValueBefore       
FROM Table2 AS t2
LEFT JOIN Table2 AS r 
   ON t2.GroupID = r.GroupID AND t2.ID >= r.ID
ORDER BY t2.ID, r.ID

производит этот вывод:

ID  GroupID ValueBefore rValueBefore
------------------------------------
1   1       10          10
2   1       15          10
2   1       15          15
3   1       5           10
3   1       5           15
3   1       5           5
4   1       5           10
4   1       5           15
4   1       5           5
4   1       5           5
5   2       40          40
6   2       30          40
6   2       30          30

Теперь вы можете рассчитать промежуточную сумму, если сгруппировать по ID и SUM по rValueBefore:

SELECT t2.ID, t2.GroupID, t2.ValueBefore, SUM(r.ValueBefore) AS Total      
FROM Table2 AS t2
LEFT JOIN Table2 AS r 
   ON t2.GroupID = r.GroupID AND t2.ID >= r.ID  
GROUP BY t2.ID, t2.GroupID, t2.ValueBefore 

Выход:

ID  GroupID ValueBefore Total
-----------------------------
1   1       10          10
2   1       15          25
3   1       5           30
4   1       5           35
5   2       40          40
6   2       30          70    

Теперь вы можете рассчитать ValueAfter, используя:

SELECT t.ID, t.GroupID, t.ValueBefore, Total,
       Subtracted,
       CASE 
          WHEN Total - t1.Subtracted  < 0 THEN 0 
          ELSE Total - t1.Subtracted
       END AS ValueAfter
FROM 
(
   SELECT t2.ID, t2.GroupID, t2.ValueBefore, SUM(r.ValueBefore) AS Total      
   FROM Table2 AS t2
   LEFT JOIN Table2 AS r 
      ON t2.GroupID = r.GroupID AND t2.ID >= r.ID  
   GROUP BY t2.ID, t2.GroupID, t2.ValueBefore
) as t
JOIN Table1 AS t1 ON t.GroupID = t1.GroupID
ORDER BY ID

Выход:

ID  GroupID ValueBefore Total   Subtracted  ValueAfter
------------------------------------------------------- 
1   1       10          10      32          0
2   1       15          25      32          0
3   1       5           30      32          0
4   1       5           35      32          3
5   2       40          40      30          10
6   2       30          70      30          40

Демо здесь

...