评估两个日期之间的工资的功能,按比例应用于部分月份

Posted

技术标签:

【中文标题】评估两个日期之间的工资的功能,按比例应用于部分月份【英文标题】:Function to evaluate a salary between two dates, applying pro rata to partial months 【发布时间】:2019-09-05 10:58:30 【问题描述】:

我需要一个函数,输入开始日期、结束日期和薪水,将计算在此期间支付的实际金额。

我可以使用带有 sum 和 group by 的日历表来做到这一点,但我想知道如果我有很多行要计算,一个函数是否会更好。

如果我们有部分月份,它将使用(薪水/12)/每月天数 * 支付天数按比例计算。

因此,如果输入 2019 年 4 月 5 日、2019 年 4 月 15 日和 250000 作为输入,则计算结果为 (25000 / 12) / 30 * 11 天(包括结束日期)= 763.89

假设 2019 年 4 月 5 日、2019 年 9 月 20 日、30000 作为输入,计算将是 (30000 / 12) / 30 * 26 天 = 2166.67(四月)

30000 / 12 * 4(4 个整月,5 月、6 月、7 月、8 月,全月率)= 10000

(30000 / 12) / 30 * 20 天 = 1666.67(9 月)

因此,2019 年 4 月 5 日至 2019 年 9 月 20 日期间的总数为 13833.34

我可以处理第一种情况,开始日期和结束日期在同一个月内,像这样

declare @startdte as date = '05 APR 2019'
declare @enddte as date = '15 APR 2019'
declare @eomed int = day(DATEADD(MONTH,1+DATEDIFF(MONTH,0,@enddte),-1)) --month end for end date
declare @salary as decimal(16,2) = 25000
select
case when year(@startdte) = year(@enddte) and month(@startdte) = month(@enddte) then @salary / 12 / @eomed * (datediff(d,@startdte, @enddte) + 1)
end

那么我能够从第二个例子中得到的唯一部分就是这将得到完整的几个月

COALESCE(NULLIF(DATEDIFF(month,@startdte-1,@enddte+1),0)-1,0)

我使用的是 SQL Server 2008 R2

【问题讨论】:

SQL Sever 2008 R2 于 2019 年 7 月 9 日停止提供扩展支持。 【参考方案1】:

这不是这么简单吗:

DECLARE @startdte AS DATE = '20180405';
DECLARE @enddte AS DATE = '20190415';
DECLARE @salary AS DECIMAL(16,2) = 25000;
SELECT
    @startdte AS [start_date],
    @enddte AS end_date,
    DATEDIFF(YEAR, @startdte, @enddte) AS years,
    DATEDIFF(DAY, @startdte, @enddte) - DATEDIFF(YEAR, @startdte, @enddte) * 365 + 1 AS [days],
    DATEDIFF(YEAR, @startdte, @enddte) * @salary
    + (DATEDIFF(DAY, @startdte, @enddte) - DATEDIFF(YEAR, @startdte, @enddte) * 365 + 1) / 365.0 * @salary AS salary_paid_over_period;

因此计算两个日期之间的年数,然后乘以薪水,然后取两个日期之间的天数,减去代表完整年份的天数,然后将其乘以薪水并除以一年中的天数。

结果:

start_date  end_date    years   days    salary_paid_over_period
2018-04-05  2019-04-15  1       11      25753.40

【讨论】:

将第二个示例用于 20190405、20190920 和 25000 得到 11575.325,这与 select @salary * (datediff(d,@startdte,@enddte) + 1) / 365 相同跨度> 抱歉,使用的是 25k 而不是 30k。它给出了 13890.39,正确的计算是 13833.34,我原来的帖子有错误 那是因为你聚合到月份,而我聚合到一天。每月工作 31 天并不会比每月工作 28 天获得更多报酬,所以我想你的方法更好?【参考方案2】:

我想我已经解决了。

declare @startdte as date = '05 APR 2019'
declare @enddte as date = '20 sep 2019'
declare @eomed int = day(DATEADD(MONTH,1+DATEDIFF(MONTH,0,@enddte),-1)) --month end for end date
declare @eomsd int = day(DATEADD(MONTH,1+DATEDIFF(MONTH,0,@startdte),-1)) --month end for start date
declare @salary as decimal(16,2) = 30000
select
case when year(@startdte) = year(@enddte) and month(@startdte) = month(@enddte) then @salary / 12 / @eomed * (datediff(d,@startdte, @enddte) + 1)
else 
(@salary / 12 / @eomsd) * (@eomsd - day(@startdte) + 1) --partial month from start date to end of month
+
datediff(month,DATEADD(m, DATEDIFF(m, -1, @startdte), 0),@enddte) * (@salary / 12) --full months from first day of month after start date to end date
+
@salary / 12 / @eomed * day(@enddte) --partial months 
end

【讨论】:

以上是关于评估两个日期之间的工资的功能,按比例应用于部分月份的主要内容,如果未能解决你的问题,请参考以下文章

JS 计算两个日期之间的月份,不足一个月按一个月计算(求大神指点)

选择按month.year分组的两个日期之间的用户计数,并且对于count = 0的月份包括零

获取两个日期之间的所有月份

java 中 判断两个日期月份的差,后面没有时分秒.比如2013-07-03与2013-09-03 返回值为2

获取两个日期之间的月份范围

求JS两个日期之间的月份数