La différence de mois entre les dates dans MySQL
-
08-07-2019 - |
Question
Je cherche à calculer le nombre de mois entre 2 champs de date et heure.
Existe-t-il un meilleur moyen que d'obtenir l'horodatage Unix, de diviser par 2 592 000 secondes et d'arrondir dans MySQL?
La solution
Le DATEDIFF fonction peut vous donner le nombre de jours entre deux dates. Qu'est-ce qui est plus précis, puisque ... comment définissez-vous un mois? (28, 29, 30 ou 31 jours?)
Autres conseils
Mois-différence entre deux dates données:
Je suis surpris que cela n'ait pas encore été mentionné:
Consultez le < strong> TIMESTAMPDIFF () dans MySQL.
Cela vous permet de transmettre deux valeurs TIMESTAMP
ou DATETIME
(ou même DATE
car MySQL sera automatiquement converti) en tant que ainsi que l'unité de temps sur laquelle vous souhaitez baser votre différence.
Vous pouvez spécifier MONTH
comme unité dans le premier paramètre:
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
Il obtient essentiellement le nombre de mois écoulés depuis la première date de la liste de paramètres. Cette solution compense automatiquement le nombre de jours variable chaque mois (28,30,31) et tient compte des années bissextiles - vous n’aurez plus à vous soucier de cela.
Différence mensuelle avec précision:
C’est un peu plus compliqué si vous souhaitez introduire une précision décimale dans le nombre de mois écoulés, mais voici comment vous pouvez le faire:
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
)
Où startdate
et enddate
sont vos paramètres de date, qu'il s'agisse de deux colonnes de date dans une table ou de paramètres d'entrée à partir d'un script:
Exemples:
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 calcule les mois entre deux dates.
Par exemple, pour calculer la différence entre now () et une colonne time dans votre_table:
select period_diff(date_format(now(), '%Y%m'), date_format(time, '%Y%m')) as months from your_table;
J'utilise aussi PERIODDIFF . Pour obtenir l'année et le mois de la date, j'utilise la fonction EXTRACT :
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;
Je préfère cette façon, car tout le monde comprendra clairement au premier regard:
SELECT
12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months
FROM
tab;
Comme le montrent de nombreuses réponses, la "bonne" réponse dépend exactement de ce dont vous avez besoin. Dans mon cas, je dois arrondir au nombre entier le plus proche .
Considérez ces exemples: 1er janvier - > 31 janvier: c'est 0 mois entiers et presque 1 mois. 1er janvier - > 1er février? C'est un mois entier et exactement un mois.
Pour obtenir le nombre de mois entiers (complets) , utilisez:
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-01-31'); => 0
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-02-01'); => 1
Pour obtenir une durée arrondie en mois, vous pouvez utiliser:
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
C’est précis à +/- 5 jours et pour des intervalles supérieurs à 1000 ans. La réponse de Zane est évidemment plus précise, mais elle est trop verbeuse à mon goût.
Du manuel MySQL:
PERIOD_DIFF (P1, P2)
Renvoie le nombre de mois entre les périodes P1 et P2. P1 et P2 doivent être au format AAMM ou AAAAMM. Notez que les arguments de période P1 et P2 ne sont pas des valeurs de date.
mysql > SELECT PERIOD_DIFF (200802,200703); - > 11
Il peut donc être possible de faire quelque chose comme ceci:
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;
Où d1 et d2 sont les expressions de date.
Je devais utiliser les instructions if () pour m'assurer que les mois étaient un nombre à deux chiffres comme 02 plutôt que 2.
Y a-t-il un meilleur moyen? Oui. N'utilisez pas les horodatages MySQL. Mis à part le fait qu'ils occupent 36 octets, ils ne sont pas du tout pratiques avec qui travailler. Je recommanderais d’utiliser Julian Date and Seconds à partir de minuit pour toutes les valeurs de date / heure. Ceux-ci peuvent être combinés pour former un UnixDateTime. Si cela est stocké dans un DWORD (entier non signé de 4 octets), les dates jusqu’à 2106 peuvent être stockées en secondes depuis epoc, 01/01/1970 DWORD max val = 4 294 967 295 - Un DWORD peut contenir 136 ans de secondes
Les dates juliennes sont très agréables à utiliser pour faire des calculs de date Les valeurs UNIXDateTime sont bonnes à utiliser pour les calculs de date / heure Il n’est pas non plus intéressant de regarder. C’est pourquoi j’utilise les horodatages lorsque j’ai besoin d’une colonne avec laquelle je ne ferai pas beaucoup de calculs, mais je veux une indication en un coup d’œil.
La conversion en julien et inversement peut être effectuée très rapidement dans un bon langage. En utilisant des pointeurs, je l’ai jusqu’à 900 Clks environ (c’est aussi une conversion de STRING en INTEGER, bien sûr)
Lorsque vous vous lancez dans des applications sérieuses qui utilisent des informations de date / heure, comme par exemple les marchés financiers, les dates en Julien sont de facto.
La requête ressemblera à:
select period_diff(date_format(now(),"%Y%m"),date_format(created,"%Y%m")) from customers where..
Donne un nombre de mois de calendrier depuis l'enregistrement de la date de création sur un enregistrement client, laissant à MySQL le choix du mois en interne.
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
Exécutez ce code et il créera une fonction datéifference qui vous donnera la différence de format de date aaaa-mm-jj.
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;
Cela dépend de la manière dont vous souhaitez définir le nombre de mois. Répondez à ces questions: «Quelle est la différence en mois: 15 février 2008 - 12 mars 2009». Est-ce défini par un nombre de jours précis qui dépend des années bissextiles, de quel mois il s’agit ou du même jour du mois précédent = 1 mois.
Un calcul pour les jours :
15 février - > 29 (année bissextile) = 14 1 mars 2008 + 365 = 1 mars 2009. 1 mars - > 12 mars = 12 jours. 14 + 365 + 12 = 391 jours. Total = 391 jours / (jours moyens dans le mois = 30) = 13,03333
Un calcul des mois :
15 fév 2008 - 15 fév 2009 2009 = 12 15 février - > 12 mars = moins de 1 mois Total = 12 mois, ou 13 si 15 février - 12 mars est considéré comme "le mois dernier"
SELECT *
FROM emp_salaryrevise_view
WHERE curr_year Between '2008' AND '2009'
AND MNTH Between '12' AND '1'
J'avais besoin de la différence de mois avec précision. Bien que la solution de Zane Bien va dans la bonne direction, ses deuxième et troisième exemples donnent des résultats inexacts. Un jour de février divisé par le nombre de jours de février n'est pas égal à un jour de mai divisé par le nombre de jours de mai. Ainsi, le deuxième exemple devrait produire ((31-5 + 1) / 31 + 13/30 =) 1,3043 et le troisième exemple ((29-27 + 1) / 29 + 2/30 + 3 =) 3.1701.
Je me suis retrouvé avec la requête suivante:
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
Vous pouvez obtenir des années, des mois et des jours de cette façon:
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
Vous pouvez également essayer ceci:
select MONTH(NOW())-MONTH(table_date) as 'Total Month Difference' from table_name;
OU
select MONTH(Newer_date)-MONTH(Older_date) as 'Total Month Difference' from table_Name;
Réponse simple en indiquant la date de début comme ins_frm et la date de fin en tant que 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
Enjoy:)))
Essayez ceci
SELECT YEAR(end_date)*12 + MONTH(end_date) - (YEAR(start_date)*12 + MONTH(start_date))
Cette requête a fonctionné pour moi:)
SELECT * FROM tbl_purchase_receipt
WHERE purchase_date BETWEEN '2008-09-09' AND '2009-09-09'
Il suffit de prendre deux dates et de récupérer les valeurs entre elles.