MySQL में तारीखों के बीच महीनों का अंतर


85

मैं 2 दिनांक समय क्षेत्रों के बीच महीनों की संख्या की गणना करना चाह रहा हूं।

क्या यूनिक्स टाइमस्टैम्प प्राप्त करने और 2 592 000 (सेकंड) से विभाजित करने और व्हिटिन MySQL को गोल करने से बेहतर तरीका है?

जवाबों:


16

DateDiff समारोह आप दो तिथियों के बीच दिनों की संख्या दे सकते हैं। जो अधिक सटीक है, क्योंकि ... आप एक महीने को कैसे परिभाषित करते हैं? (२ 30, २ ९, ३०, या ३१ दिन?)


68
PERIODDIFF महीनों की संख्या की सही गणना कर सकता है।
अधिकतम Caceres

10
"अधिक सटीक" अविश्वसनीय व्यक्तिपरक है जब यह तिथियों की बात आती है। यदि, उदाहरण के लिए, आप एक व्यवसाय में हैं, जिसमें मासिक चक्र हैं, तो यह जानने की आवश्यकता है कि दो तिथियों के बीच कितने महीने हैं, आपके द्वारा ऊपर बताए गए दिनों के लिए दिनों की संख्या से अधिक महत्वपूर्ण हो सकता है। एक महीना कब तक है? अगर मुझे एक महीने की गिनती की आवश्यकता है तो मैं बस 30 से विभाजित नहीं कर सकता।
थॉमस पेन

6
यह सही उत्तर नहीं है; आपको नीचे मैक्स के उत्तर को सही अंकित करना चाहिए ।
ग्राहम चार्ल्स

1
मैक्स का उत्तर सही नहीं है यदि आप पूरे महीनों की संख्या, छलांग वर्षों के लिए सही ढंग से और एक महीने में दिनों की अलग-अलग संख्या चाहते हैं। PERIODDIFFबस एक YYYMM मान लेता है, इसलिए जब तक आप YYYMM मानों को पास करने से पहले खुद को दिनों के लिए खाते हैं, तो आप सभी की गणना कर रहे हैं महीनों की संख्या है, निकटतम महीने तक गोल किया जाता है अगर पूरे महीने से कम है। नीचे ज़ैन का जवाब देखें।
rgvcorley

2
PERIODDIFFटिप्पणी के लिए इतने सारे अपवित्र क्यों हैं ? पीरियडडिफ़ दिन के मूल्यों को नहीं लेता है, इसलिए आप महीनों की संख्या की गणना निकटतम महीने तक कर सकते हैं यदि महीने की पूरी संख्या से कम है
rgvcorley

218

किसी भी दो तिथियों के बीच महीने का अंतर:

मुझे आश्चर्य है कि यह अभी तक उल्लेख नहीं किया गया है:

MySQL में TIMESTAMPDIFF () फ़ंक्शन पर एक नज़र डालें ।

यह आपको क्या करने की अनुमति देता है दो 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

8
यह सही उत्तर है, PERIODDIFFचयनित उत्तर पर टिप्पणी के लिए सभी upvotes बहुत मिस कर रहे हैं
rgvcorley

5
धन्यवाद, मेरे मामले में मुझे समावेशी तारीखों की आवश्यकता थी, इसलिए मैं सभी "एंडडेट" को "डेट_एड" (एंडडेट, इंटरवल 1 दिन) के साथ बदल देता हूं। फिर 2014-03-01 से 2014-05-31 में 2.97 के बजाय 3.00 देंगे
स्वेन तोरे

2
बहुत बहुत धन्यवाद ..... "सटीक के साथ महीना-अंतर:" के लिए विशेष धन्यवाद। आप
Vidhi

1
माना। यह सही जवाब है। ठीक वही जो मेरे द्वारा खोजा जा रहा था! धन्यवाद।
जॉन वोट

104

PERIOD_DIFF दो तिथियों के बीच महीनों की गणना करता है।

उदाहरण के लिए, अब और () के बीच अंतर की गणना करने के लिए और अपने समय में कॉलम:

select period_diff(date_format(now(), '%Y%m'), date_format(time, '%Y%m')) as months from your_table;

1
किसी भी विचार यह क्या करता है जब यह 11 महीने और 1 दिन हो सकता है, तो 12 महीने, लेकिन अगर आप 30 दिन के महीनों में बदलते हैं तो यह अभी भी 11 होगा?
डैरिल हेन

1
11 महीने और 1 दिन उपरोक्त उदाहरण के साथ 11 महीने लौटेगा। PERIOD_DIFF का 30 बनाम 31 दिन महीनों का कोई अर्थ नहीं है।
मैक्स

26

मैं भी PERIODDIFF का उपयोग करता हूं । साल और तारीख के महीने प्राप्त करने के लिए, मैं फ़ंक्शन का उपयोग EXTRACT :

  SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;

2
अतुल्य! यह उस DATE_FORMATविधि का 50% कम समय का उपयोग करता है, धन्यवाद! +1
डेविड रोड्रिग्स

1
यहाँ एक यूनिक्स टाइमस्टैम्प के लिए SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM FROM_UNIXTIME(time, "%Y%m%d"))) AS months FROM your_table;
स्मोल्ला

2
यह गलत है, PERIOD_DIFFदिन के मूल्यों को नहीं लेता है, इसलिए यदि आप महीनों की संख्या की गणना कर रहे हैं, तो निकटतम माह तक हो सकता है, अगर पूरे महीने की संख्या कम है। इसे स्पष्ट करने के लिए आपको अपना उत्तर संपादित करना चाहिए।
rgvcorley

12

यहाँ जितने भी उत्तर दिखाई देते हैं, 'सही' उत्तर वास्तव में आपकी ज़रूरत पर निर्भर करता है। मेरे मामले में, मुझे निकटतम पूरी संख्या में चक्कर लगाना होगा

इन उदाहरणों पर विचार करें: 1 जनवरी -> 31 जनवरी: यह 0 पूरे महीने है, और लगभग 1 महीने लंबा है। 1 जनवरी -> 1 फरवरी? यह 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 साल से अधिक की सीमाओं के लिए सटीक है। ज़ैन का जवाब स्पष्ट रूप से अधिक सटीक है, लेकिन यह मेरी पसंद के लिए बहुत अधिक क्रिया है।


मैं असहमत हूं ... SELECT TIMESTAMPDIFF (MONTH, '2018-01-31', '2018-02-04'); आपको 0 महीने अलग करता है ... SELECT TIMESTAMPDIFF (MONTH, '2018-01-31', '2018-03-01); आपको 1 देता है ... यदि 5 दिन 0 है, तो 29 दिन 1 है?
स्कॉट

@ सच, ​​जनवरी और मार्च के बीच एक पूरा महीना (जिसे फरवरी कहा जाता है) है। TIMESTAMPDIFF बस तारीखों के बीच पूरे महीने की संख्या देता है। यदि आप किसी भी महीने के आकार की अवधि एक महीने के बराबर करना चाहते हैं, तो मेरे द्वारा दिए गए गोल संस्करण का उपयोग करें।
आईएएनएस

8

MySQL मैनुअल से:

PERIOD_DIFF (P1, P2)

पी 1 और पी 2 के बीच महीनों की संख्या लौटाता है। P1 और P2 प्रारूप YYMM या YYYMM में होना चाहिए। ध्यान दें कि पी 1 और पी 2 की अवधि तर्क तारीख मान नहीं है।

mysql> SELECT PERIOD_DIFF (200802,200703); -> ११

तो ऐसा कुछ करना संभव हो सकता है:

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 तारीख के भाव हैं।

मुझे यह सुनिश्चित करने के लिए कि () कथनों का उपयोग करना है, यह सुनिश्चित करने के लिए कि महीने 2 के बजाय 02 की तरह दो अंकों की संख्या थे।


8

मैं इस तरह से पसंद करता हूं, क्योंकि evryone इसे पहली नज़र में स्पष्ट रूप से समझ जाएगा:

SELECT
    12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months
FROM
    tab;

स्टेनिस्लाव - यह विधि बिलकुल सही है यदि आप BY MONTH NUMBER का डेटा जानना चाहते हैं। मेरे पास कुछ रिपोर्टें हैं जो महीने (जनवरी / फरवरी / मार्च आदि) से बिक्री दिखाती हैं, लेकिन इतना अधिक डेटा (चार्ट / तिमाही / वर्ष / पिछले वर्षों आदि से चार्ट) है कि मैं कुछ भी समूह नहीं कर सकता। मुझे इसके माध्यम से कच्चे डेटा और लूप में खींचने की आवश्यकता है - जब यह 1/31 है, तो कई गणनाएं "अगले महीने" मार्च में डालती हैं जब हम मनुष्य जानते हैं कि यह फ़रवरी है। यदि यह 2/4 है, तो कुछ गणना कहते हैं कि 1/31 "यह महीना" है, लेकिन 1/28 "आखिरी महीना" था
स्कॉट

6

क्या कोई बेहतर तरीका है? हाँ। MySQL टाइमस्टैम्प का उपयोग न करें। इस तथ्य के अलावा कि वे 36 बाइट्स पर कब्जा कर लेते हैं, वे साथ काम करने के लिए बिल्कुल भी सुविधाजनक नहीं हैं। मैं सभी तिथि / समय मानों के लिए आधी रात से जूलियन डेट और सेकंड्स का उपयोग करना चाहूंगा। इन्हें यूनिक्सडेटटाइम बनाने के लिए जोड़ा जा सकता है। यदि यह एक DWORD में संग्रहीत किया जाता है (4 बाइट इंटर्गर) तो तारीख 2106 तक सभी तरह से सेकंड के रूप में संग्रहीत किया जा सकता है, 01/01/1970 DWORD अधिकतम वैल = 4,294,967,295 - एक DWORD 136 साल का सेकंड रख सकता है

जूलियन डेट्स तारीख गणना करते समय काम करने के लिए बहुत अच्छी हैं। UNIXDateTime मान काम करने के लिए अच्छे हैं जब दिनांक / समय की गणना करते समय काम करना अच्छा होता है। के साथ, लेकिन मैं एक नज़र संकेत चाहते हैं।

जूलियन और बैक में कनवर्ट करना एक अच्छी भाषा में बहुत जल्दी किया जा सकता है। पॉइंटर्स का उपयोग करते हुए मैंने इसे लगभग 900 क्लिक्स में बदल दिया है (यह STRING से INTEGER के पाठ्यक्रम में रूपांतरण भी है)

जब आप गंभीर अनुप्रयोगों में आते हैं जो वित्तीय बाजारों उदाहरण के लिए दिनांक / समय की जानकारी का उपयोग करते हैं, तो जूलियन तिथियां वास्तविक हैं।


आपको इस तथ्य के बारे में जानकारी कहां से मिली कि वे 36 बाइट पर कब्जा करते हैं ? MySQL मैनुअल में TIMESTAMP कॉलम के लिए स्टोरेज की आवश्यकता 4 बाइट्स हैdev.mysql.com/doc/refman/5.1/en/storage-requirements.html
poncha

अब Y2106 बग के लिए योजना बनाना शुरू करें! ;-)
ErichBSchulz

5

प्रश्न इस प्रकार होगा:

select period_diff(date_format(now(),"%Y%m"),date_format(created,"%Y%m")) from customers where..

एक ग्राहक रिकॉर्ड पर बनाए गए डेटास्टैम्प के बाद से कई कैलेंडर महीने देता है, जिससे MySQL महीने का चयन आंतरिक रूप से करता है।


2
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

2

इस कोड को निष्पादित करें और यह एक फ़ंक्शन 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;

1
क्या आपको लगता है कि आप अपने कोड को साफ और टिप्पणी कर सकते हैं, इसलिए यह थोड़ा अधिक समझने योग्य है? धन्यवाद
डैरिल हेन

1

यह इस बात पर निर्भर करता है कि आप किस तरह से # महीनों की परिभाषा चाहते हैं। इस प्रश्न का उत्तर दें: 'महीनों में क्या अंतर है: फरवरी 15, 2008 - मार्च 12, 2009'। क्या यह उन दिनों के स्पष्ट कट द्वारा परिभाषित किया गया है जो लीप वर्ष पर निर्भर करता है- यह किस महीने का है, या पिछले महीने का एक ही दिन = 1 महीना।

दिनों के लिए एक गणना :

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 को 'पिछला महीना' माना जाता है



1

मुझे सटीकता के साथ महीने-अंतर की आवश्यकता थी। हालाँकि ज़ेन बायन का समाधान सही दिशा में है, लेकिन उनके दूसरे और तीसरे उदाहरण गलत परिणाम देते हैं। फरवरी में एक दिन का विभाजन फरवरी में दिनों की संख्या से विभाजित होता है, मई में एक दिन के बराबर नहीं। तो दूसरा उदाहरण आउटपुट ((31-5 + 1) / 31 + 13/30 =) 1.3043 और तीसरा उदाहरण ((29-27 + 1) / 29 + 2/30 + 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

1

PERIOD_DIFF () फ़ंक्शन

एक तरह से MySQL PERIOD_DIFF () दो अवधियों के बीच का अंतर लौटाता है। पीरियड्स एक ही फॉर्मेट यानी YYYMM या YYMM में होने चाहिए। यह ध्यान दिया जाना चाहिए कि अवधि तिथि मान नहीं हैं।

कोड:

SELECT PERIOD_DIFF(200905,200811);

यहां छवि विवरण दर्ज करें


0

आप इस तरह से वर्ष, महीने और दिन प्राप्त कर सकते हैं:

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

0

आप यह भी आज़मा सकते हैं:

select MONTH(NOW())-MONTH(table_date) as 'Total Month Difference' from table_name;

या

select MONTH(Newer_date)-MONTH(Older_date) as 'Total Month Difference' from table_Name;

0

सरल उत्तर दिए गए प्रारंभ दिनांक 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

का आनंद लें :)))


0

इसे इस्तेमाल करे

SELECT YEAR(end_date)*12 + MONTH(end_date) - (YEAR(start_date)*12 + MONTH(start_date))

ढेर अतिप्रवाह में आपका स्वागत है! प्रश्नों पर तारीख की जाँच करना सुनिश्चित करें और क्या मौजूदा उत्तरों का एक ही समाधान है।
लेहिस्टर

-1

इस क्वेरी ने मेरे लिए काम किया :)

SELECT * FROM tbl_purchase_receipt
WHERE purchase_date BETWEEN '2008-09-09' AND '2009-09-09'

यह केवल दो तिथियां लेता है और उनके बीच के मूल्यों को पुनः प्राप्त करता है।


पूरी तरह से गलत जवाब, वह महीनों की गिनती चाहता है
शेन रौट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.