如何使用 MySQL 查询获取两个日期之间的月差?
我正在计算两个日期时间字段之间的月数。
有没有比获取 Unix 时间戳然后除以 2 592 000(秒)并在 MySQL 中向上舍入更好的方法?
I'm looking to calculate the number of months between 2 date time fields.
Is there a better way than getting the Unix timestamp and then dividing by 2 592 000 (seconds) and rounding up within MySQL?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(21)
任何给定两个日期之间的月差:
我很惊讶这一点还没有被提及:
看看 TIMESTAMPDIFF() MySQL 中的函数。
这允许您传入两个
TIMESTAMP
或DATETIME
值(甚至是DATE
,因为 MySQL 会自动转换)以及您想要作为差异基础的时间单位。您可以在第一个参数中指定
MONTH
作为单位:它基本上获取从参数列表中的第一个日期开始经过的月数。 该解决方案会自动补偿每个月不同的天数(28、30、31),并考虑闰年 - 您不必担心任何这些问题。
精确的月差:
如果您想在经过的月份数中引入小数精度,那就有点复杂了,但可以这样做:
其中
startdate
和enddate 是您的日期参数,无论是来自表中的两个日期列还是来自脚本的输入参数:
示例:
Month-difference between any given two dates:
I'm surprised this hasn't been mentioned yet:
Have a look at the TIMESTAMPDIFF() function in MySQL.
What this allows you to do is pass in two
TIMESTAMP
orDATETIME
values (or evenDATE
as MySQL will auto-convert) as well as the unit of time you want to base your difference on.You can specify
MONTH
as the unit in the first parameter:It basically gets the number of months elapsed from the first date in the parameter list. This solution automatically compensates for the varying amount of days in each month (28,30,31) as well as taking into account leap years — you don't have to worry about any of that stuff.
Month-difference with precision:
It's a little more complicated if you want to introduce decimal precision in the number of months elapsed, but here is how you can do it:
Where
startdate
andenddate
are your date parameters, whether it be from two date columns in a table or as input parameters from a script:Examples:
PERIOD_DIFF 计算月份两个日期之间。
例如,要计算 now() 与 your_table 中的时间列之间的差异:
PERIOD_DIFF calculates months between two dates.
For example, to calculate the difference between now() and a time column in your_table:
我还使用 PERIOD_DIFF。 为了获取日期的年份和月份,我使用函数 摘录:
I use also PERIOD_DIFF. To get the year and the month of the date, I use the function EXTRACT:
DATEDIFF 函数可以给出您两个日期之间的天数。 哪个更准确,因为……你如何定义一个月? (28、29、30 还是 31 天?)
The DATEDIFF function can give you the number of days between two dates. Which is more accurate, since... how do you define a month? (28, 29, 30, or 31 days?)
正如这里的许多答案所示,“正确”的答案取决于您的需求。 就我而言,我需要四舍五入到最接近的整数。
考虑这些例子:
1 月 1 日 -> 1月31日:整整0个月,差不多1个月了。
1 月 1 日 -> 2月1日? 整整1个月,正好1个月长。
要获取整个(完整)月数,请使用:
要获取以月为单位的四舍五入持续时间,您可以使用:
这精确到 +/- 5 天,并且适用于范围超过1000年。 赞恩的回答显然更准确,但对我来说太冗长了。
As many of the answers here show, the 'right' answer depends on exactly what you need. In my case, I need to round to the closest whole number.
Consider these examples:
1st January -> 31st January: It's 0 whole months, and almost 1 month long.
1st January -> 1st February? It's 1 whole month, and exactly 1 month long.
To get the number of whole (complete) months, use:
To get a rounded duration in months, you could use:
This is accurate to +/- 5 days and for ranges over 1000 years. Zane's answer is obviously more accurate, but it's too verbose for my liking.
我更喜欢这种方式,因为大家一看就明白:
I prefer this way, because evryone will understand it clearly at the first glance:
来自 MySQL 手册:
因此,可以执行如下操作:
其中 d1 和 d2 是日期表达式。
我必须使用 if() 语句来确保月份是两位数,例如 02 而不是 2。
From the MySQL manual:
So it may be possible to do something like this:
Where d1 and d2 are the date expressions.
I had to use the if() statements to make sure that the months was a two digit number like 02 rather than 2.
有没有更好的办法?
是的。 不要使用 MySQL 时间戳。 除了占用 36 字节之外,它们使用起来一点也不方便。
我建议对所有日期/时间值使用朱利安日期和午夜开始的秒数。
这些可以组合起来形成 UnixDateTime。 如果将其存储在 DWORD(无符号 4 字节整数)中,则一直到 2106 的日期都可以存储为自 epoc, 01/01/1970 以来的秒数
DWORD max val = 4,294,967,295 - DWORD 可以保存 136 年的秒数
在进行日期计算时,儒略日期非常适合使用
进行日期/时间计算时,UNIXDateTime 值非常适合使用
两者都不好看,所以当我需要一个不会进行太多计算的列,但我想要一个概览指示时,我会使用时间戳。
使用良好的语言可以非常快速地完成与 Julian 的相互转换。 使用指针,我将其减少到大约 900 个时钟(当然,这也是从字符串到整数的转换)
当您进入使用日期/时间信息的严肃应用程序(例如金融市场)时,儒略日期实际上是。
Is there a better way?
yes. Do not use MySQL Timestamps. Apart from the fact that they occupy 36 Bytes, they are not at all convenient to work with.
I would reccomend using Julian Date and Seconds from midnight for all date/time values.
These can be combined to form a UnixDateTime. If this is stored in a DWORD (unsigned 4 Byte Integer) then dates all the way up to 2106 can be stored as seconds since epoc, 01/01/1970
DWORD max val = 4,294,967,295 - A DWORD can hold 136 years of Seconds
Julian Dates are very nice to work with when making date calculations
UNIXDateTime values are good to work with when making Date/Time calculations
Neither are good to look at, so I use the Timestamps when I need a column that I will not be doing much calculation with, but I want an at-a-glance indication.
Converting to Julian and back can be done very quickly in a good language. Using pointers I have it down to about 900 Clks (This is also a conversion from a STRING to an INTEGER of course)
When you get into serious applications that use Date/Time information like for example the financial markets, Julian dates are de-facto.
查询将类似于:
给出自在客户记录上创建日期戳以来的多个日历月,让 MySQL 在内部进行月份选择。
The Query will be like:
Gives a number of calendar months since the created datestamp on a customer record, letting MySQL do the month selection internally.
执行此代码,它将创建一个函数 datedeifference,它将为您提供日期格式 yyyy-mm-dd 的差异。
Execute this code and it will create a function datedeifference which will give you the difference in date format yyyy-mm-dd.
这取决于您希望如何定义月份数。 回答以下问题:“月份有何不同:2008 年 2 月 15 日 - 2009 年 3 月 12 日”。 它是由明确的天数定义的,这取决于闰年 - 是哪一个月,还是上个月的同一天 = 1 个月。
天数计算:
2 月 15 日 -> 29(闰年)= 14
2008 年 3 月 1 日 + 365 = 2009 年 3 月 1 日。
3月1日-> 3 月 12 日 = 12 天。
14 + 365 + 12 = 391 天。
总计 = 391 天 /(每月平均天数 = 30)= 13.03333
月份计算:
2008 年 2 月 15 日 - 2009 年 2 月 15 日 = 12
2月15日-> 3 月 12 日 = 不到 1 个月
总计 = 12 个月,如果 2 月 15 日 - 3 月 12 日被视为“过去一个月”,则为 13 个月
This depends on how you want the # of months to be defined. Answer this questions: 'What is difference in months: Feb 15, 2008 - Mar 12, 2009'. Is it defined by clear cut # of days which depends on leap years- what month it is, or same day of previous month = 1 month.
A calculation for Days:
Feb 15 -> 29 (leap year) = 14
Mar 1, 2008 + 365 = Mar 1, 2009.
Mar 1 -> Mar 12 = 12 days.
14 + 365 + 12 = 391 days.
Total = 391 days / (avg days in month = 30) = 13.03333
A calculation of months:
Feb 15 2008 - Feb 15 2009 = 12
Feb 15 -> Mar 12 = less than 1 month
Total = 12 months, or 13 if feb 15 - mar 12 is considered 'the past month'
我需要精确的月差。 尽管 Zane Bien 的解决方案方向正确,但他的第二个和第三个示例给出的结果不准确。 二月的一天除以二月的天数不等于五月的一天除以五月的天数。 因此,第二个示例应输出 ((31-5+1)/31 + 13/30 = ) 1.3043,第三个示例应输出 ((29-27+1)/29 + 2/30 + 3 = ) 3.1701。
我最终得到以下查询:
I needed month-difference with precision. Although Zane Bien's solution is in the right direction, his second and third examples give inaccurate results. A day in February divided by the number of days in February is not equal to a day in May divided by the number of days in May. So the second example should output ((31-5+1)/31 + 13/30 = ) 1.3043 and the third example ((29-27+1)/29 + 2/30 + 3 = ) 3.1701.
I ended up with the following query:
PERIOD_DIFF() 函数
其中一种方法是 MySQL PERIOD_DIFF() 返回两个周期之间的差异。 期间应采用相同的格式,即 YYYYMM 或 YYMM。 需要注意的是,句点不是日期值。
代码:
PERIOD_DIFF() function
One of the way is MySQL PERIOD_DIFF() returns the difference between two periods. Periods should be in the same format i.e. YYYYMM or YYMM. It is to be noted that periods are not date values.
Code:
您可以通过以下方式获取年、月和日:
You can get years, months and days this way:
您也可以尝试以下操作:
或
You can also try this:
OR
简单的答案是给定开始日期为 ins_frm 和结束日期为 ins_to
Enjoy :)))
Simple answer given start date as ins_frm and end date as ins_to
Enjoy :)))
尝试这个
Try this
虽然这是一个老话题,但它显示在谷歌的顶部,我没有看到与 Mysql 相关的新问题来计算几个月的差异。 我需要一个非常精确的计算,包括月份的一部分。
这是为了计算订阅费,例如每月 8 欧元。 那么二月的 1 天与其他月份相比确实有不同的价格。 所以需要计算月份的分数,这里分数的精度是基于秒的。
它的作用是在@from和@to日期之间计算时将计算分成3部分:
例如,从 '2021-09-29 12 :00:00' 到 '2021-11-07 00:00:00':
天,因此分数为 0.05 个月 (1.5/30)。
所以结果是 1.25 个月。
完全相同的计算,但现在基于不使用 mysql 变量的人的字段,并且更容易接管自己的字段:
为了速度优化,我使用了
unix_timestamp
,它应该执行得很快,因为它能够使用数学计算。unix_timestamp
返回一个以秒为单位的数字。 86400 是一天的秒数。Although it's an old topic it shows on top in google and I don't see newer questions related to Mysql to calculate the difference in months. And I needed a very precise calculation including the fraction of the month.
This for the purpose to calculate a subscription fee e.g. 8 euro per month. Then 1 day in februari does have a different price compared to other months. So the fraction of months needs to be calculated and here the precision of the fraction is based on seconds.
What it does is to split the calculation into 3 parts when calculation between @from and @to dates:
E.g from '2021-09-29 12:00:00' to '2021-11-07 00:00:00':
days so the fraction is 0.05 month (1.5/30).
So the outcome is 1.25 month.
Exactly the same calculation but now based on fields for people not using mysql variables and easier to take over your own fields:
For speed optimization I've used
unix_timestamp
which should perform fast as it is able to use mathematic calculation. Theunix_timestamp
returns a number in seconds. The 86400 is the number of seconds in a day.这个查询对我有用:)
它只需要两个日期并检索它们之间的值。
This query worked for me:)
It simply take two dates and retrieves the values between them.