Summing multiple columns per row, with dynamic amount to calculate.

huangapple go评论65阅读模式
英文:

Summing multiple columns per row, with dynamic amount to calculate

问题

以下是已翻译的内容:

有一个用于计算加班工时的表格:

id worker_id extra_hours_1_5x_amount extra_hours_1_5x_sum extra_hours_2x_amount extra_hours_2x_sum extra_hours_3x_amount extra_hours_3x_sum is_approved approved_amount
1 222 2 100 1 60 null null yes null
2 333 2 150 2 200 1 120 no null
3 444 2 50 2 100 3 180 part 6

(Fiddle: https://dbfiddle.uk/Plsd2pdX)

该表格表示每位工人的额外工时,以及额外工时的类型(基本工资的1.5倍、2倍或3倍),以及支付这些工时的实际金额。

我想根据批准类型选择每行的总批准金额 - 如果批准了,那么将所有金额(1.5倍、2倍和3倍金额)相加。如果未批准,则总金额为0。

如果部分批准,则从更高的金额开始累加部分批准金额。在上面的示例中,第三行部分批准了5小时,所以应从3倍开始逐渐累加。因此,首先将3小时从3倍中取出,然后从2倍中取出2小时,最后从1.5倍中取出1小时,然后将它们相加:

180 + 100 + (50/2*1) = 305

因此结果应为:

worker_id total_sum
222 160
333 0
444 305

我考虑使用CASE,但问题是,如果批准类型是部分批准,那么我还需要在从更高类型到更低类型逐渐累加时计算剩余的额外工时,我无法在CASE内部完成这个操作。

英文:

There is a table for calculating extra-time working hours:

id worker_id extra_hours_1_5x_amount extra_hours_1_5x_sum extra_hours_2x_amount extra_hours_2x_sum extra_hours_3x_amount extra_hours_3x_sum is_approved approved_amount
1 222 2 100 1 60 null null yes null
2 333 2 150 2 200 1 120 no null
3 444 2 50 2 100 3 180 part 6

(Fiddle: https://dbfiddle.uk/Plsd2pdX)

The table represents the extra hours for each worker, and which type of extra hour is it (1.5x, 2x or 3x of base salary), and the actual amount to pay for these hours.

I want to select the total approved sum of each row based on the approval type - if it's approved, then sum all the sums (1.5x, 2x and 3x sums). If it's not approved, it will be 0.

If it's partially approved, sum the partial approved sum, starting from the higher amount. In the above example, the 3rd row is partially approved with 5 hours, so it should start summing from the 3x to below. so take all the 3 hours from the 3x, and then 2 hours from the 2x, and 1 remaining hour from the 1.5x, which will then be summed up to:

180 + 100 + (50/2*1) = 305

so the result would be:

worker_id total_sum
222 160
333 0
444 305

I thought about using CASE, but the problem here is that if the approved type is partial, then I also need to count the remaining extra hours as I go from the higher to the lower type and I was not able to do it inside the CASE

答案1

得分: 1

以下是翻译好的代码部分:

这里是一个潜在的解决方案:

select worker_id
, sum(case when is_approved = 'yes' then s when is_approved = 'no' then 0
   else case when aggtime <= approved_amount then s else s / (h * 1.0 * (aggtime - approved_amount))  end  end)
  , approved_amount
  from (
SELECT e.id, e.worker_id, is_approved, approved_amount, h.*
   , sum(h.h) over(partition by worker_id order by sort desc) as aggTime
  FROM extraTime e
cross apply (
    select extra_hours_1_5x_amount as h, extra_hours_1_5x_sum as s, 1 as sort
     union all
    select extra_hours_2x_amount,extra_hours_2x_sum, 2
   union all
  select extra_hours_3x_amount, extra_hours_3x_sum, 3
    ) h
  ) x
group by worker_id,approved_amount
order by worker_id

我对代码进行了翻译,去除了其他内容。

英文:

Here's a potential solution:


select worker_id
, sum(case when is_approved = &#39;yes&#39; then s when is_approved = &#39;no&#39; then 0
   else case when aggtime &lt;= approved_amount then s else s / (h * 1.0 * (aggtime - approved_amount))  end  end)
  , approved_amount
  from (
SELECT e.id, e.worker_id, is_approved, approved_amount, h.*
   , sum(h.h) over(partition by worker_id order by sort desc) as aggTime
  FROM extraTime e
cross apply (
    select extra_hours_1_5x_amount as h, extra_hours_1_5x_sum as s, 1 as sort
     union all
    select extra_hours_2x_amount,extra_hours_2x_sum, 2
   union all
  select extra_hours_3x_amount, extra_hours_3x_sum, 3
    ) h
  ) x
group by worker_id,approved_amount
order by worker_id

I do a little unpivot to get the hours separated and aggregate them ordered by approval hours starting from the highest.
Then to get the total sum, i check which of the approval condition is applied and do the formula you mentioned

答案2

得分: 0

以下是您要翻译的内容:

这是我解决问题的想法
有3个case语句,我需要解释的是"when部分"。

select worker_id, 
       case is_approved
         when 'yes' then isnull(extra_hours_1_5x_sum, 0) + isnull(extra_hours_2x_sum, 0) + isnull(extra_hours_3x_sum, 0)
         when 'part' then /* 计算3x小时获批准的 */ least(isnull(approved_amount, 0), isnull(extra_hours_3x_amount, 0)) * (isnull(extra_hours_3x_sum, 1) / isnull(extra_hours_3x_amount, 1)) +
                          /* 计算2x小时获批准的(如果剩下的话) */  least(isnull(approved_amount, 0) - isnull(extra_hours_3x_amount, 0), isnull(extra_hours_2x_amount, 0)) * (isnull(extra_hours_2x_sum, 1) / isnull(extra_hours_2x_sum, 1)) + 
                          /* 计算1.5x小时获批准的(如果剩下的话) */least(isnull(approved_amount, 0) - isnull(extra_hours_3x_amount, 0) - isnull(extra_hours_2x_amount, 0), isnull(extra_hours_1_5x_amount, 0)) * (isnull(extra_hours_1_5x_sum, 0) / isnull(extra_hours_1_5x_amount, 0))
         when 'no' then 0
       end total_sum
  from extraTime

"when 'part'" 的解释如下:
第一行计算了每小时的3x小时价格

isnull(extra_hours_3x_sum, 1) / isnull(extra_hours_3x_amount, 1)

并将其与approved_amount或extra_hours_3x_amount相乘,取较小的那个。

第二和第三行执行以下操作:它获取了前面步骤剩余的时间量

least(isnull(approved_amount, 0) - isnull(extra_hours_3x_amount, 0), isnull(extra_hours_2x_amount, 0))

并将其与2x和1_5x小时的相应小时价格相乘。

这不是通用解决方案,但应该适用于您的特定情况。

请查看dbfiddle

英文:

Here is my idea of how to solve it
There are 3 case statements and the "when part" part is the one I need to explain.

select worker_id, 
       case is_approved
         when &#39;yes&#39; then isnull(extra_hours_1_5x_sum, 0) + isnull(extra_hours_2x_sum, 0) + isnull(extra_hours_3x_sum, 0)
         when &#39;part&#39; then /* calculate 3x hours approved */          least(isnull(approved_amount, 0), isnull(extra_hours_3x_amount, 0)) * (isnull(extra_hours_3x_sum, 1) / isnull(extra_hours_3x_amount, 1)) +
                          /* calculate 2x hours approved if left */  least(isnull(approved_amount, 0) - isnull(extra_hours_3x_amount, 0), isnull(extra_hours_2x_amount, 0)) * (isnull(extra_hours_2x_sum, 1) / isnull(extra_hours_2x_sum, 1)) + 
                          /* calculate 1.5x hours approved if left */least(isnull(approved_amount, 0) - isnull(extra_hours_3x_amount, 0) - isnull(extra_hours_2x_amount, 0), isnull(extra_hours_1_5x_amount, 0)) * (isnull(extra_hours_1_5x_sum, 0) / isnull(extra_hours_1_5x_amount, 0))
         when &#39;no&#39; then 0
       end total_sum
  from extraTime

The "when 'part'" explanation:
first line calculates 3x_hour pro hour price

isnull(extra_hours_3x_sum, 1) / isnull(extra_hours_3x_amount, 1)

and multiplies it with either approved_amount or extra_hours_3x_amount.Depending on which one is smaller.

second and third line do the following: it takes amount of time left from previous steps

least(isnull(approved_amount, 0) - isnull(extra_hours_3x_amount, 0), isnull(extra_hours_2x_amount, 0))

and multiplies it with respective hour price for 2x of 1_5x hours.

It's not a universal solution but it should be working for your specific case

Check the dbfiddle

huangapple
  • 本文由 发表于 2023年4月19日 15:58:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76052029.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定