MYSQL如何在MYSQL中执行两个日期之间的自定义月差



我的要求是在两个日期之间分别计算总月份和细分月份(即表中的第一个日期和第二个日期为当前日期(。如果断月总数>15,则将其视为一个月的经验,如果少于15,则不将其视为由一个月经验。

假设我表上的日期为2018年11月25日,当前日期为2019年1月6日;中间的一个月是12月,所以有1个月的经验;破碎的月份是11月和1月,所以现在我必须计算11月的6天和1月的6日,所以是12天,并且<=(lte(15,因此总经验将四舍五入为1个月的经验

我从stackoverflow中引用了多个与MYSQL中计算日期差有关的问题,但找不到任何可能的选项。MYSQL TIMESTAMPDIFF、TIMEDIFF、PERIOD_DIFF、DATE_DIFF中的内置函数没有给出我需要的结果,因为它们的算法与我的计算要求不同。

任何关于如何在MYSQL中执行此计算并将其结果作为SQL语句的一部分的线索都将对我有所帮助。一旦到达该值,在同一SQL中,该值将被验证为在给定的值范围内。

包括示例表结构&值:

table_name = "user"
id | name | join_date 
---------------------
1| Sam | 25-11-2017
2| Moe | 03-04-2017
3| Tim | 04-07-2018
4| Sal | 30-01-2017
5| Joe | 13-08-2018

我想从上表中找出那些根据上述逻辑以月为单位计算经验的用户。如果这些月份在以下任一范围之间,则提取这些用户以进行进一步处理。

table_name: "allowed_exp_range"
starting_exp_months | end_exp_months
-------------------------------------
0 | 6
9 | 24

例如:根据我的计算,Sam到目前为止(2018年10月10日(的经验是12+1个月=13个月。由于13在9&24日,Sam的记录是预期产出之一。

我认为这个查询可以满足您的要求。它使用

(YEAR(CURDATE())*12+MONTH(CURDATE()))
- (YEAR(STR_TO_DATE(join_date, '%d-%m-%Y'))*12+MONTH(STR_TO_DATE(join_date, '%d-%m-%Y'))) -
- 1

为了获得用户整个月的经验,

DAY(LAST_DAY(STR_TO_DATE(join_date, '%d-%m-%Y')))
- DAY(STR_TO_DATE(join_date, '%d-%m-%Y'))
+ 1

获取第一个月的天数,以及

DAY(CURDATE())

以获取当前月份的天数。两天的计数相加,如果总数>15,则整个月的数量加1,例如

SELECT id
, name
, (YEAR(CURDATE())*12+MONTH(CURDATE())) - (YEAR(STR_TO_DATE(join_date, '%d-%m-%Y'))*12+MONTH(STR_TO_DATE(join_date, '%d-%m-%Y'))) - 1 -- whole months
+ CASE WHEN DAY(LAST_DAY(STR_TO_DATE(join_date, '%d-%m-%Y'))) - DAY(STR_TO_DATE(join_date, '%d-%m-%Y')) + 1 + DAY(CURDATE()) > 15 THEN 1 ELSE 0 END -- broken month
AS months
FROM user

我们可以使用这个表达式作为userallowed_exp_range之间的JOIN条件,以找到在给定范围内有经验的所有用户:

SELECT u.id
, u.name
, a.starting_exp_months
, a.end_exp_months
FROM user u
JOIN allowed_exp_range a
ON (YEAR(CURDATE())*12+MONTH(CURDATE())) - (YEAR(STR_TO_DATE(u.join_date, '%d-%m-%Y'))*12+MONTH(STR_TO_DATE(u.join_date, '%d-%m-%Y'))) - 1
+ CASE WHEN DAY(LAST_DAY(STR_TO_DATE(u.join_date, '%d-%m-%Y'))) - DAY(STR_TO_DATE(u.join_date, '%d-%m-%Y')) + 1 + DAY(CURDATE()) > 15 THEN 1 ELSE 0 END
BETWEEN a.starting_exp_months AND a.end_exp_months

输出(对于您的样本数据,包括所有用户,因为他们都符合其中一个体验范围(:

id  name    starting_exp_months     end_exp_months
1   Sam     9                       24
2   Moe     9                       24
3   Tim     0                       6
4   Sal     9                       24
5   Joe     0                       6

我在dbfiddle上创建了一个小演示,演示了获得结果的步骤。

最新更新