Ich möchte die Anzahl der Monate zwischen zwei Datums- und Uhrzeitfeldern 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?
Ich möchte die Anzahl der Monate zwischen zwei Datums- und Uhrzeitfeldern 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?
Antworten:
PERIODDIFF
Nimmt einfach einen JJJJMM-Wert an. Wenn Sie also nicht die Tage selbst berücksichtigen, bevor Sie die JJJJMM-Werte übergeben, berechnen Sie nur die Anzahl der Monate, aufgerundet auf den nächsten Monat, wenn weniger als eine ganze Anzahl von Monaten vorhanden ist. Siehe Zanes Antwort unten.
PERIODDIFF
Kommentar? Perioddiff nimmt keine Tageswerte an, daher berechnen Sie die Anzahl der Monate, die auf den nächsten Monat aufgerundet werden, wenn weniger als eine ganze Anzahl von Monaten vorhanden ist
Ich bin überrascht, dass dies noch nicht erwähnt wurde:
Schauen Sie sich die Funktion TIMESTAMPDIFF () in MySQL an.
Auf diese Weise können Sie zwei TIMESTAMP
oder mehr DATETIME
Werte (oder sogar, DATE
wenn MySQL automatisch konvertiert) sowie die Zeiteinheit übergeben, auf die Sie Ihre Differenz stützen möchten.
Sie können MONTH
im ersten Parameter 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
Grundsätzlich wird die Anzahl der Monate angegeben, die seit dem ersten Datum in der Parameterliste vergangen sind. Diese Lösung kompensiert automatisch die unterschiedliche Anzahl von Tagen in jedem Monat (28, 30, 31) sowie die Berücksichtigung von Schaltjahren - Sie müssen sich um nichts davon kümmern.
Es ist etwas komplizierter, wenn Sie in der Anzahl der verstrichenen Monate eine Dezimalgenauigkeit einführen möchten, aber so können Sie dies tun:
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
)
Wo startdate
und enddate
sind Ihre Datumsparameter, sei es aus zwei Datumsspalten in einer Tabelle oder als Eingabeparameter aus einem Skript:
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
PERIODDIFF
Kommentar zur ausgewählten Antwort sind sehr
PERIOD_DIFF berechnet Monate zwischen zwei Daten.
So berechnen Sie beispielsweise die Differenz zwischen now () und einer Zeitspalte in your_table:
select period_diff(date_format(now(), '%Y%m'), date_format(time, '%Y%m')) as months from your_table;
Ich benutze auch PERIODDIFF . Um das Jahr und den Monat des Datums zu erhalten, benutze ich die Funktion EXTRACT :
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;
DATE_FORMAT
Methode benötigt 50% weniger Zeit , danke! +1
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM FROM_UNIXTIME(time, "%Y%m%d"))) AS months FROM your_table;
PERIOD_DIFF
nimmt keine Tageswerte an, daher berechnen Sie die Anzahl der auf den nächsten Monat aufgerundeten Monate, wenn weniger als eine ganze Anzahl von Monaten vorhanden ist. Sie sollten Ihre Antwort bearbeiten, um dies zu verdeutlichen.
Wie viele der Antworten hier zeigen, hängt die richtige Antwort genau davon ab, was Sie brauchen. In meinem Fall muss ich auf die nächste ganze Zahl runden .
Betrachten Sie diese Beispiele: 1. Januar -> 31. Januar: Es sind 0 ganze Monate und fast 1 Monat lang. 1. Januar -> 1. Februar? Es ist 1 ganzer Monat und genau 1 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 und für Bereiche über 1000 Jahre genau. Zanes Antwort ist offensichtlich genauer, aber für meinen Geschmack zu ausführlich.
Aus dem MySQL-Handbuch:
PERIOD_DIFF (P1, P2)
Gibt die Anzahl der Monate zwischen den Perioden P1 und P2 zurück. P1 und P2 sollten das Format JJJM oder JJJJM 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;
Wobei d1 und d2 die Datumsausdrücke sind.
Ich musste die if () - Anweisungen verwenden, um sicherzustellen, dass die Monate eine zweistellige Zahl wie 02 statt 2 waren.
Ich bevorzuge diesen Weg, weil jeder ihn auf den ersten Blick klar verstehen wird:
SELECT
12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months
FROM
tab;
Gibt es einen besseren Weg? Ja. Verwenden Sie keine MySQL-Zeitstempel. Abgesehen von der Tatsache, dass sie 36 Bytes belegen, ist es überhaupt nicht bequem, mit ihnen zu arbeiten. Ich würde empfehlen, Julian Date und Seconds ab Mitternacht für alle Datums- / Zeitwerte zu verwenden. Diese können zu einer UnixDateTime kombiniert werden. Wenn dies in einem DWORD (vorzeichenlose 4-Byte-Ganzzahl) gespeichert ist, können Daten bis zu 2106 als Sekunden seit dem Epoc gespeichert werden. 01.01.1970 DWORD max val = 4.294.967.295 - Ein DWORD kann 136 Jahre lang halten
Julian Dates sind sehr gut zu bearbeiten, wenn Datumsberechnungen durchgeführt werden. UNIXDateTime-Werte sind gut zu verwenden, wenn Datums- / Uhrzeitberechnungen durchgeführt werden mit, aber ich möchte einen Blick auf einen Blick.
Das Konvertieren zu Julian und zurück kann sehr schnell in einer guten Sprache erfolgen. Mit Zeigern habe ich es auf ungefähr 900 Clks reduziert (dies ist natürlich auch eine Konvertierung von einem STRING zu einem INTEGER).
Wenn Sie in ernsthafte Anwendungen geraten, die Datums- / Uhrzeitinformationen wie beispielsweise die Finanzmärkte verwenden, sind julianische Daten de facto.
Die Abfrage lautet wie folgt:
select period_diff(date_format(now(),"%Y%m"),date_format(created,"%Y%m")) from customers where..
Gibt eine Anzahl von Kalendermonaten seit dem erstellten Datenstempel in einem Kundendatensatz an, sodass MySQL die Monatsauswahl intern vornehmen kann.
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
Wenn Sie diesen Code ausführen, wird eine Funktion mit Datumsdifferenz erstellt, die den Unterschied im Datumsformat JJJJ-MM-TT anzeigt.
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;
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 eindeutige Anzahl von Tagen definiert, die von den Schaltjahren abhängt - welcher Monat es ist oder der gleiche Tag des Vormonats = 1 Monat.
Eine Berechnung für Tage :
15. Februar -> 29 (Schaltjahr) = 14. 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 der Monate :
15. Februar 2008 - 15. Februar 2009 = 12. Februar 15 -> 12. März = weniger als 1 Monat Gesamt = 12 Monate oder 13, wenn der 15. Februar - 12. März als "letzter Monat" betrachtet wird
SELECT *
FROM emp_salaryrevise_view
WHERE curr_year Between '2008' AND '2009'
AND MNTH Between '12' AND '1'
Ich brauchte einen Monatsunterschied mit Präzision. Obwohl die Lösung von Zane Bien 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 entspricht nicht 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.
Am Ende hatte ich folgende 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
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
Sie können dies auch versuchen:
select MONTH(NOW())-MONTH(table_date) as 'Total Month Difference' from table_name;
ODER
select MONTH(Newer_date)-MONTH(Older_date) as 'Total Month Difference' from table_Name;
Diese Abfrage hat bei mir funktioniert :)
SELECT * FROM tbl_purchase_receipt
WHERE purchase_date BETWEEN '2008-09-09' AND '2009-09-09'
Es dauert einfach zwei Daten und ruft die Werte zwischen ihnen ab.