سؤال

أنا أتطلع لحساب عدد الأشهر بين حقلي التاريخ والوقت.

هل هناك طريقة أفضل من الحصول على الطابع الزمني لنظام التشغيل 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

وأنا أيضا استخدام 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;

الدالة PERIOD_DIFF()

إحدى الطرق هي أن يقوم MySQL PERIOD_DIFF() بإرجاع الفرق بين فترتين.يجب أن تكون الفترات بنفس التنسيق، أي.YYYYMM أو YYMM.وتجدر الإشارة إلى أن الفترات ليست قيم التاريخ.

شفرة:

SELECT PERIOD_DIFF(200905,200811);

enter image description here

وبسيطة الجواب تاريخ البدء كما 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'

وانها ببساطة تأخذ تاريخين ويسترد القيم بينهما.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top