【问题标题】:MYSQL How to perform custom month difference between two dates in MYSQL?MYSQL 如何在 MYSQL 中执行两个日期之间的自定义月差?
【发布时间】:2018-12-10 05:05:41
【问题描述】:

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

假设我在桌子上的日期是 25/11/2018,当前日期是 06/01/2019; 中间的整月是 12 月,所以有 1 个月的经验;坏月份是 11 月和 1 月,所以现在我必须计算日期,即 11 月 6 天和 1 月 6 天,所以 12 天

我提到了多个与从 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 迄今为止 (10-12-2018) 的经验是 12+1 个月 = 13 个月。由于 13 介于 9 和 24 之间,因此 Sam 的记录是预期输出之一。

【问题讨论】:

  • 5/11/201820/12/2018 是 0 个月和 2 个破月共 47 天吗?
  • 是的@Nick,如果总天数是 47 天,因为它大于我的 15 天限制,所以差值被认为是 1 个月。
  • 如果有人有兴趣对任何问题投反对票,请提供评论并说明投反对票的原因。否则,OP 永远不会知道出了什么问题,从而很有可能重复同样的事情。所以,请表现出同样的兴趣来解释你投反对票的原因。
  • @Malathy 我已根据您对问题所做的更改更新了我的答案。

标签: mysql date date-difference


【解决方案1】:

我认为这个查询会做你想做的事。它使用

  (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,它演示了获得结果的步骤。

【讨论】:

  • 感谢@Nick 的时间和回答!您的回答帮助我得出了预期的输出。
  • 嗨@Nick,你能告诉你这个帖子的答案吗? stackoverflow.com/questions/53768236/…?
  • @Malathy 对不起-我不知道 eloquent/laravel 所以我不能帮你解决这个问题。我相信其他人也能做到。
猜你喜欢
  • 2011-08-03
  • 2010-09-22
  • 2014-08-22
  • 2011-06-13
  • 1970-01-01
  • 2011-06-06
相关资源
最近更新 更多