الفرق في الأشهر بين التواريخ في MySQL
-
08-07-2019 - |
سؤال
أنا أتطلع لحساب عدد الأشهر بين حقلي التاريخ والوقت.
هل هناك طريقة أفضل من الحصول على الطابع الزمني لنظام التشغيل Unix والقسمة على 2592000 (ثانية) والتقريب ضمن MySQL؟
المحلول
DATEDIFF وظيفة يمكن أن تعطيك عدد الأيام بين تاريخين. وهو أكثر دقة، منذ ... كيف تعرف في الشهر؟ (28، 29، 30، أو 31 يوما؟)
نصائح أخرى
فرق الشهر بين أي تاريخين محددين:
أنا مندهش أنه لم يتم ذكر هذا بعد:
الق نظرة على TIMESTAMPDIFF() وظيفة في MySQL.
ما يسمح لك هذا بفعله هو التمرير إلى قسمين TIMESTAMP
أو DATETIME
القيم (أو حتى DATE
حيث سيتم تحويل MySQL تلقائيًا) بالإضافة إلى وحدة الوقت التي تريد أن يبني عليها الفرق.
يمكنك تحديد MONTH
كوحدة في المعلمة الأولى:
SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-04')
-- Outputs: 0
SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-05')
-- Outputs: 1
SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-15')
-- Outputs: 1
SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-12-16')
-- Outputs: 7
إنه يحصل بشكل أساسي على عدد الأشهر المنقضية من التاريخ الأول في قائمة المعلمات.يعوض هذا الحل تلقائيًا مقدار الأيام المتغيرة في كل شهر (28،30،31) بالإضافة إلى مراعاة السنوات الكبيسة - لا داعي للقلق بشأن أي من هذه الأشياء.
الفرق الشهري بدقة:
يكون الأمر أكثر تعقيدًا بعض الشيء إذا كنت تريد إدخال الدقة العشرية في عدد الأشهر المنقضية، ولكن إليك كيفية القيام بذلك:
SELECT
TIMESTAMPDIFF(MONTH, startdate, enddate) +
DATEDIFF(
enddate,
startdate + INTERVAL
TIMESTAMPDIFF(MONTH, startdate, enddate)
MONTH
) /
DATEDIFF(
startdate + INTERVAL
TIMESTAMPDIFF(MONTH, startdate, enddate) + 1
MONTH,
startdate + INTERVAL
TIMESTAMPDIFF(MONTH, startdate, enddate)
MONTH
)
أين startdate
و enddate
هي معلمات التاريخ، سواء كانت من عمودين للتاريخ في جدول أو كمعلمات إدخال من برنامج نصي:
أمثلة:
With startdate = '2012-05-05' AND enddate = '2012-05-27':
-- Outputs: 0.7097
With startdate = '2012-05-05' AND enddate = '2012-06-13':
-- Outputs: 1.2667
With startdate = '2012-02-27' AND enddate = '2012-06-02':
-- Outputs: 3.1935
PERIOD_DIFF أ > بحساب الأشهر بين تاريخين.
وعلى سبيل المثال، لحساب الفرق بين الآن () وعمود الوقت في your_table:
select period_diff(date_format(now(), '%Y%m'), date_format(time, '%Y%m')) as months from your_table;
وأنا أيضا استخدام PERIODDIFF . للحصول على السنة والشهر من تاريخ، وأنا استخدم وظيفة <لأ href = "http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_extract" يختلط = "noreferrer"> استخراج :
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;
وأنا أفضل هذه الطريقة، لأن الجميع سوف يفهم بشكل واضح في أول وهلة:
SELECT
12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months
FROM
tab;
كما تظهر العديد من الإجابات هنا، فإن الإجابة "الصحيحة" تعتمد على ما تحتاجه بالضبط.في حالتي، أنا بحاجة إلى ذلك التقريب إلى أقرب عدد صحيح.
خذ بعين الاعتبار هذه الأمثلة:1 يناير -> 31 يناير:إنها 0 أشهر كاملة، وحوالي شهر واحد.1 يناير -> 1 فبراير؟إنه شهر كامل، ومدة شهر واحد بالضبط.
للحصول على عدد كامل (كامل) أشهر، استخدم:
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-01-31'); => 0
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-02-01'); => 1
للحصول على مدور المدة بالأشهر، يمكنك استخدام:
SELECT ROUND(TIMESTAMPDIFF(DAY, '2018-01-01', '2018-01-31')*12/365.24); => 1
SELECT ROUND(TIMESTAMPDIFF(DAY, '2018-01-01', '2018-01-31')*12/365.24); => 1
هذا دقيق حتى +/- 5 أيام ولمدى يزيد عن 1000 عام.من الواضح أن إجابة زين أكثر دقة، لكنها مطولة جدًا بما لا يروق لي.
ومن دليل الخلية:
<اقتباس فقرة>وPERIOD_DIFF (P1، P2)
وإرجاع عدد الأشهر بين فترات P1 و P2. يجب أن تكون P1 و P2 في YYMM شكل أو YYYYMM. لاحظ أن P1 الحجج فترة وP2 ليست قيم التاريخ.
ك> SELECT PERIOD_DIFF (200802،200703)؛ -> 11
اقتباس فقرة>وهكذا قد يكون من الممكن أن تفعل شيئا من هذا القبيل:
Select period_diff(concat(year(d1),if(month(d1)<10,'0',''),month(d1)), concat(year(d2),if(month(d2)<10,'0',''),month(d2))) as months from your_table;
وأين D1 و D2 هي تعبيرات التاريخ.
واضطررت لاستخدام البيانات إذا () للتأكد من أن الأشهر كانت رقم اثنين أرقام مثل 02 بدلا من 2.
هل هناك طريقة أفضل؟ نعم. لا تستخدم الخلية الطوابع. وبصرف النظر عن حقيقة أنها تحتل 36 بايت، فهي ليست على الإطلاق مريحة للعمل مع. وأود أن أوصى باستخدام جوليان التاريخ وبعد ثوان من منتصف الليل لجميع قيم التاريخ / الوقت. هذه يمكن أن تكون جنبا إلى جنب لتشكيل UnixDateTime. إذا تم تخزين هذا في DWORD (غير موقعة 4 بايت عدد صحيح) ثم يعود كل وسيلة تصل إلى 2106 ويمكن تخزين كما ثواني منذ إيبوك، 01/01/1970 ماكس DWORD فال = 4294967295 - A DWORD يمكن ان تحمل 136 سنة من ثانية
وتواريخ جوليان لطيفة جدا للعمل مع عند اتخاذ حسابات التاريخ قيم UNIXDateTime جيدة للعمل مع عند اتخاذ التسجيل حسابات / الوقت لا هي جيدة لننظر، ولذا فإنني استخدام الطوابع عندما كنت في حاجة عمود أنني لن نفعل الكثير الحساب معها، ولكن أريد مؤشرا في لمحة.
والتحويل إلى جوليان والظهر ويمكن أن يتم بسرعة كبيرة بلغة جيدة. باستخدام مؤشرات لدي إلى حوالي 900 Clks (وهذا هو أيضا التحويل من STRING إلى عدد صحيح طبعا)
وعندما تحصل في التطبيقات الخطيرة التي تستخدم معلومات التاريخ / الوقت مثل على سبيل المثال الأسواق المالية، وبحكم الواقع مواعيد جوليان.
وسوف الاستعلام يكون مثل:
select period_diff(date_format(now(),"%Y%m"),date_format(created,"%Y%m")) from customers where..
ويعطي عددا من أشهر تقويمية منذ تاريخ الختم إنشاؤها على سجل العملاء، والسماح الخلية القيام اختيار الشهر داخليا.
DROP FUNCTION IF EXISTS `calcula_edad` $$
CREATE DEFINER=`root`@`localhost` FUNCTION `calcula_edad`(pFecha1 date, pFecha2 date, pTipo char(1)) RETURNS int(11)
Begin
Declare vMeses int;
Declare vEdad int;
Set vMeses = period_diff( date_format( pFecha1, '%Y%m' ), date_format( pFecha2, '%Y%m' ) ) ;
/* Si el dia de la fecha1 es menor al dia de fecha2, restar 1 mes */
if day(pFecha1) < day(pFecha2) then
Set vMeses = VMeses - 1;
end if;
if pTipo='A' then
Set vEdad = vMeses div 12 ;
else
Set vEdad = vMeses ;
end if ;
Return vEdad;
End
select calcula_edad(curdate(),born_date,'M') -- for number of months between 2 dates
وتنفيذ هذا الرمز وأنه سيتم إنشاء datedeifference وظيفة والتي سوف تعطيك الفرق في تنسيق التاريخ YYYY-MM-DD.
DELIMITER $$
CREATE FUNCTION datedifference(date1 DATE, date2 DATE) RETURNS DATE
NO SQL
BEGIN
DECLARE dif DATE;
IF DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2)))) < 0 THEN
SET dif=DATE_FORMAT(
CONCAT(
PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))DIV 12 ,
'-',
PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))% 12 ,
'-',
DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(DATE_SUB(date1, INTERVAL 1 MONTH)), '-', DAY(date2))))),
'%Y-%m-%d');
ELSEIF DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2)))) < DAY(LAST_DAY(DATE_SUB(date1, INTERVAL 1 MONTH))) THEN
SET dif=DATE_FORMAT(
CONCAT(
PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))DIV 12 ,
'-',
PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))% 12 ,
'-',
DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2))))),
'%Y-%m-%d');
ELSE
SET dif=DATE_FORMAT(
CONCAT(
PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))DIV 12 ,
'-',
PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))% 12 ,
'-',
DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2))))),
'%Y-%m-%d');
END IF;
RETURN dif;
END $$
DELIMITER;
يعتمد هذا على الطريقة التي تريد بها تحديد عدد الأشهر.أجب عن هذه الأسئلة:'ما هو الفرق في الأشهر:15 فبراير 2008 - 12 مارس 2009'.هل يتم تحديده من خلال عدد واضح من الأيام التي تعتمد على السنوات الكبيسة - ما هو الشهر، أو نفس اليوم من الشهر السابق = شهر واحد.
حساب للأيام:
15 فبراير -> 29 (سنة قفزة) = 14 مارس 1 ، 2008 + 365 = 1 مارس 2009.1 مارس -> 12 مارس = 12 يومًا.14 + 365 + 12 = 391 يومًا.الإجمالي = 391 يومًا / (متوسط عدد أيام الشهر = 30) = 13.03333
حساب الأشهر:
فبراير 15 2008 - فبراير 15 2009 = 12 فبراير 15 -> مارس 12 = أقل من 1 شهر الإجمالي = 12 شهرا ، أو 13 إذا كان 15 فبراير - 12 مارس يعتبر "الشهر الماضي"
SELECT *
FROM emp_salaryrevise_view
WHERE curr_year Between '2008' AND '2009'
AND MNTH Between '12' AND '1'
وأنا في حاجة أشهر الفرق بدقة. على الرغم من أن الحل زين بيين هو في الاتجاه الصحيح، له أمثلة الثانية والثالثة تعطي نتائج غير دقيقة. يوم في فبراير مقسوما على عدد الأيام في شهر فبراير ليست على قدم المساواة إلى يوم مايو مقسوما على عدد الأيام في شهر مايو. لذلك ينبغي المثال الثاني الإخراج ((31-5 + 1) / 31 + 13/30 =) 1.3043 والمثال الثالث ((29-27 + 1) / 29 + 30/02 + 3 =) 3.1701.
وانتهى بي الأمر مع الاستعلام التالي:
SELECT
'2012-02-27' AS startdate,
'2012-06-02' AS enddate,
TIMESTAMPDIFF(DAY, (SELECT startdate), (SELECT enddate)) AS days,
IF(MONTH((SELECT startdate)) = MONTH((SELECT enddate)), 0, (TIMESTAMPDIFF(DAY, (SELECT startdate), LAST_DAY((SELECT startdate)) + INTERVAL 1 DAY)) / DAY(LAST_DAY((SELECT startdate)))) AS period1,
TIMESTAMPDIFF(MONTH, LAST_DAY((SELECT startdate)) + INTERVAL 1 DAY, LAST_DAY((SELECT enddate))) AS period2,
IF(MONTH((SELECT startdate)) = MONTH((SELECT enddate)), (SELECT days), DAY((SELECT enddate))) / DAY(LAST_DAY((SELECT enddate))) AS period3,
(SELECT period1) + (SELECT period2) + (SELECT period3) AS months
ويمكنك الحصول على السنوات والأشهر والأيام بهذه الطريقة:
SELECT
username
,date_of_birth
,DATE_FORMAT(CURDATE(), '%Y') - DATE_FORMAT(date_of_birth, '%Y') - (DATE_FORMAT(CURDATE(), '00-%m-%d') < DATE_FORMAT(date_of_birth, '00-%m-%d')) AS years
,PERIOD_DIFF( DATE_FORMAT(CURDATE(), '%Y%m') , DATE_FORMAT(date_of_birth, '%Y%m') ) AS months
,DATEDIFF(CURDATE(),date_of_birth) AS days
FROM users
ويمكنك أيضا محاولة هذا:
select MONTH(NOW())-MONTH(table_date) as 'Total Month Difference' from table_name;
وOR
select MONTH(Newer_date)-MONTH(Older_date) as 'Total Month Difference' from table_Name;
وبسيطة الجواب تاريخ البدء كما ins_frm وتاريخ انتهاء كما ins_to
SELECT convert(TIMESTAMPDIFF(year, ins_frm, ins_to),UNSIGNED) as yrs,
mod(TIMESTAMPDIFF(MONTH, ins_frm, ins_to),12) mnths
FROM table_name
واستمتع:)))
وهذه محاولة
SELECT YEAR(end_date)*12 + MONTH(end_date) - (YEAR(start_date)*12 + MONTH(start_date))
وعملت هذا الاستعلام بالنسبة لي:)
SELECT * FROM tbl_purchase_receipt
WHERE purchase_date BETWEEN '2008-09-09' AND '2009-09-09'
وانها ببساطة تأخذ تاريخين ويسترد القيم بينهما.