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

MYSQL How to perform custom month difference between two dates in MYSQL?

我的要求是分别计算两个日期之间的总月数和细分月数(即 table 的第一个日期,第二个日期是当前日期)。如果破月总数> 15,则将其计为 1 个月的经验,如果小于 15 则不要将其计为 1 个月的经验。

假设我在 table 的日期是 25/11/2018,当前日期是 06/01/2019; 中间的整月是 12 月,所以 1 个月的经验;破月是 11 月和 1 月,所以现在我必须计算日期,即 11 月 6 天和 1 月 6 天,所以 12 天并且 <= (lte) 15 所以总经验将四舍五入为 1 个月的经验

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

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

包括示例 table 结构和值:

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的用户,他们的体验是根据上述逻辑以月为单位计算的。如果这些月份在以下任一范围之间,则会提取这些用户以进行进一步处理。

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

例如:根据我的计算,Sam 截至日期 (10-12-2018) 的经验是 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

我创建了一个小的 demo on dbfiddle 来演示获得结果的步骤。