webentwicklung-frage-antwort-db.com.de

Der Unterschied in Monaten zwischen Daten in MySQL

Ich möchte die Anzahl der Monate zwischen zwei Datumszeitfeldern berechnen.

Gibt es einen besseren Weg, als den Unix-Zeitstempel und die Division durch 2 592 000 (Sekunden) zu erhalten und innerhalb von MySQL aufzurunden?

63
Darryl Hein

Die Funktion DATEDIFF gibt Ihnen die Anzahl der Tage zwischen zwei Datumsangaben an. Was ist genauer, seit ... wie definieren Sie einen Monat? (28, 29, 30 oder 31 Tage?)

18
SoapBox

Monatliche Differenz zwischen zwei beliebigen Daten:

Ich bin überrascht, dass dies noch nicht erwähnt wurde:

Schauen Sie sich die Funktion TIMESTAMPDIFF () in MySQL an.

Sie können also zwei TIMESTAMP- oder DATETIME-Werte übergeben (oder sogar DATE, da MySQL automatisch konvertiert) sowie die Zeiteinheit, auf die Sie Ihre Differenz stützen möchten.

Sie können im ersten Parameter MONTH als Einheit angeben:

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

Im Wesentlichen wird die Anzahl der Monate ab dem ersten Datum in der Parameterliste angezeigt. Diese Lösung gleicht automatisch die unterschiedliche Anzahl von Tagen in jedem Monat (28, 30, 31) aus und berücksichtigt auch Schaltjahre - Sie müssen sich keine Sorgen um irgendetwas machen.


Monatsunterschied mit Präzision:

Es ist etwas komplizierter, wenn Sie die abgelaufenen Monate mit einer Dezimalgenauigkeit versehen möchten, aber wie Sie dies tun können:

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
  )

Wobei startdate und enddate Ihre Datumsparameter sind, entweder aus zwei Datumsspalten einer Tabelle oder als Eingabeparameter eines Skripts:

Beispiele:

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
169
Zane Bien

PERIOD_DIFF berechnet Monate zwischen zwei Datumsangaben.

So berechnen Sie beispielsweise die Differenz zwischen now () und einer Zeitspalte in Ihrer_Tabelle:

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

Ich benutze auch PERIODDIFF . Um das Jahr und den Monat des Datums zu erhalten, verwende ich die Funktion EXTRACT :

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

Wie viele der Antworten hier zeigen, hängt die „richtige“ Antwort davon ab, was Sie genau brauchen. In meinem Fall muss ich auf die nächste ganze Zahl runden.

Betrachten Sie diese Beispiele: 1. Januar -> 31. Januar: Es ist 0 ganze Monate und fast 1 Monat lang. 1. Januar -> 1. Februar? Es ist ein ganzer Monat und genau ein Monat lang.

Um die Anzahl der ganzen (vollständigen) Monate zu erhalten, verwenden Sie:

SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-01-31');  => 0
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-02-01');  => 1

Um eine gerundete Dauer in Monaten zu erhalten, können Sie Folgendes verwenden:

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

Dies ist auf +/- 5 Tage genau und gilt für Bereiche über 1000 Jahre. Zanes Antwort ist offensichtlich genauer, aber zu ausführlich für meinen Geschmack.

8
IanS

Ich bevorzuge diesen Weg, weil jeder es auf den ersten Blick klar verstehen wird:

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

Aus dem MySQL-Handbuch:

PERIOD_DIFF (P1, P2)

Gibt die Anzahl der Monate zwischen den Zeiträumen P1 und P2 zurück. P1 und P2 sollten das Format YYMM oder YYYYMM haben. Beachten Sie, dass die Periodenargumente P1 und P2 keine Datumswerte sind.

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

So kann es möglich sein, so etwas zu tun:

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;

Dabei sind d1 und d2 die Datumsausdrücke.

Ich musste die if () -Anweisungen verwenden, um sicherzustellen, dass die Monate eine zweistellige Zahl wie 02 und nicht 2 sind. 

7

Gibt es einen besseren Weg? Ja. Verwenden Sie keine MySQL-Zeitmarken. Abgesehen von der Tatsache, dass sie 36 Bytes einnehmen, ist es überhaupt nicht günstig, mit .. zu arbeiten. Ich würde Julian Date und Seconds ab Mitternacht für alle Datums-/Zeitwerte empfehlen. Diese können zu einem Datum kombiniert werden UnixDateTime. Wenn dieser Wert in einem DWORD (vorzeichenloser 4 Byte Integer) gespeichert wird, können Datumsangaben bis 2106 als Sekunden seit dem Epoc, 01.01.1970, gespeichert werden DWORD max val = 4.294.967.295 - Ein DWORD kann 136 Jahre halten Sekunden 

Julian Dates sind sehr nett, wenn Sie mit Datumsberechnungen arbeiten. UNIXDateTime-Werte sind gut für Datums-/Zeitberechnungen geeignet. __ Beide sind nicht gut anzusehen. Ich benutze die Zeitstempel, wenn ich eine Spalte brauche, die ich brauche Ich werde nicht viel mit rechnen, aber ich möchte einen Überblick.

Das Konvertieren in Julianisch und zurück ist in einer guten Sprache sehr schnell möglich. Mit Zeigern habe ich es auf ca. 900 Clks (Dies ist natürlich auch eine Umwandlung von STRING in INTEGER)

Bei ernsthaften Anwendungen, die Datums-/Uhrzeitinformationen wie beispielsweise die Finanzmärkte verwenden, sind Julianische Daten de facto.

6
Mike Trader

Die Abfrage wird wie folgt aussehen:

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

Gibt eine Anzahl von Kalendermonaten seit der Erstellung des Datumsstempels in einem Kundendatensatz an, wobei MySQL die Monatsauswahl intern durchführen lässt. 

5
Mike Harrison
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
Rama

Führen Sie diesen Code aus und es wird eine Funktion mit Datumsunterschied erstellt, die Ihnen den Unterschied im Datumsformat gibt.

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;
2
enor
SELECT * 
FROM emp_salaryrevise_view 
WHERE curr_year Between '2008' AND '2009' 
    AND MNTH Between '12' AND '1'
1
JAVED

Ich brauchte genau die Differenz des Monats. Obwohl Zane Biens Lösung in die richtige Richtung geht, liefern sein zweites und drittes Beispiel ungenaue Ergebnisse. Ein Tag im Februar, geteilt durch die Anzahl der Tage im Februar, ist nicht gleich einem Tag im Mai, geteilt durch die Anzahl der Tage im Mai. Das zweite Beispiel sollte also ((31-5 + 1)/31 + 13/30 =) 1.3043 und das dritte Beispiel ((29-27 + 1)/29 + 2/30 + 3 =) 3.1701 ausgeben. 

Ich endete mit der folgenden Abfrage:

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
Michel Mix

Dies hängt davon ab, wie die Anzahl der Monate definiert werden soll. Beantworten Sie diese Fragen: "Was ist der Unterschied in Monaten: 15. Februar 2008 - 12. März 2009". Wird es durch eine klare Anzahl von Tagen definiert, die von den Schaltjahren abhängt - je nachdem, um welchen Monat es sich handelt, oder um denselben Tag des vorherigen Monats = 1 Monat.

Eine Berechnung für Tage :

15. Februar -> 29 (Schaltjahr) = 14 1. März 2008 + 365 = 1. März 2009 . 1. März -> 12. März = 12 Tage 14 + 365 + 12 = 391 Tage . Gesamt = 391 Tage/(durchschnittliche Tage im Monat = 30) = 13.03333

Eine Berechnung von Monaten

15. Februar 2008 - 15. Februar 2009 = 12 15. Februar -> 12. März = weniger als 1 MonatGesamt = 12 Monate oder 13, wenn 15. - 12. März als der letzte Monat betrachtet wird 

1
Klathzazt

PERIOD_DIFF () - Funktion

Eine der Möglichkeiten ist MySQL. PERIOD_DIFF () gibt die Differenz zwischen zwei Perioden zurück. Perioden sollten im gleichen Format sein, d. H. YYYYMM oder YYMM. Es ist zu beachten, dass Perioden keine Datumswerte sind.

Code:

SELECT PERIOD_DIFF(200905,200811);

 enter image description here

0
Amitesh

Sie können dies auch versuchen:

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;
0
Shubham Verma

Sie können Jahre, Monate und Tage auf diese Weise erhalten:

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
Artur Kędzior

Einfache Antwort mit Startdatum als ins_frm und Enddatum als 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

Genießen :)))

0
Mo Kassab

Versuche dies

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