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
我们可以将此表达式用作 user
和 allowed_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 来演示获得结果的步骤。
我的要求是分别计算两个日期之间的总月数和细分月数(即 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
我们可以将此表达式用作 user
和 allowed_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 来演示获得结果的步骤。