Pregunta

Estoy buscando calcular la cantidad de meses entre 2 campos de fecha y hora.

¿Hay una mejor manera que obtener la marca de tiempo de Unix y dividir por 2 592 000 (segundos) y redondear dentro de MySQL?

¿Fue útil?

Solución

El DATEDIFF La función puede darle el número de días entre dos fechas. ¿Qué es más preciso, ya que ... cómo define un mes? (28, 29, 30 o 31 días?)

Otros consejos

diferencia de mes entre dos fechas:

Me sorprende que esto no se haya mencionado todavía:

Eche un vistazo al < strong> TIMESTAMPDIFF () en MySQL.

Lo que esto le permite hacer es pasar dos valores TIMESTAMP o DATETIME (o incluso DATE ya que MySQL se convertirá automáticamente) como así como la unidad de tiempo en la que desea basar su diferencia.

Puede especificar MES como la unidad en el primer parámetro:

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

Básicamente obtiene el número de meses transcurridos desde la primera fecha en la lista de parámetros. Esta solución compensa automáticamente la cantidad variable de días de cada mes (28, 30, 31), además de tener en cuenta los años bisiestos & # 8212; no tienes que preocuparte por nada de eso.


Mes de diferencia con precisión:

Es un poco más complicado si quieres introducir precisión decimal en el número de meses transcurridos, pero así es como puedes hacerlo:

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
  )

Donde startdate y enddate son sus parámetros de fecha, ya sea de dos columnas de fecha en una tabla o como parámetros de entrada de un script:

Ejemplos:

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 calcula meses entre dos fechas.

Por ejemplo, para calcular la diferencia entre now () y una columna de tiempo en your_table:

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

Yo uso también PERIODDIFF . Para obtener el año y el mes de la fecha, utilizo la función EXTRACTO :

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

Prefiero esta manera, porque todos lo entenderán claramente a primera vista:

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

Como muestran muchas de las respuestas aquí, la respuesta 'correcta' depende exactamente de lo que necesita. En mi caso, necesito redondear al número entero más cercano .

Considere estos ejemplos: 1 de enero - > 31 de enero: son 0 meses completos y casi 1 mes. 1 de enero - > 1 de febrero? Es 1 mes entero y exactamente 1 mes de duración.

Para obtener la cantidad de meses completos (completos) , use:

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

Para obtener una duración redondeada en meses, puede usar:

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

Esto tiene una precisión de +/- 5 días y para rangos de más de 1000 años. La respuesta de Zane es obviamente más precisa, pero es demasiado detallada para mi gusto.

Del manual de MySQL:

  

PERIOD_DIFF (P1, P2)

     

Devuelve el número de meses entre los períodos P1 y P2. P1 y P2 deben estar en el formato YYMM o YYYYMM. Tenga en cuenta que los argumentos de período P1 y P2 no son valores de fecha.

     

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

Entonces puede ser posible hacer algo como esto:

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;

Donde d1 y d2 son las expresiones de fecha.

Tuve que usar las declaraciones if () para asegurarme de que los meses fueran un número de dos dígitos como 02 en lugar de 2.

¿Hay una mejor manera? sí. No use las marcas de tiempo MySQL. Aparte del hecho de que ocupan 36 Bytes, no es conveniente trabajar con ellos. Recomendaría usar Julian Date y Seconds from midnight para todos los valores de fecha / hora. Estos se pueden combinar para formar UnixDateTime. Si esto se almacena en un DWORD (entero de 4 bytes sin signo), las fechas hasta 2106 se pueden almacenar como segundos desde epoc, 01/01/1970 DWORD max val = 4,294,967,295 - Un DWORD puede contener 136 años de segundos

Julian Dates es muy agradable para trabajar al hacer cálculos de fechas Es bueno trabajar con los valores UNIXDateTime al hacer cálculos de fecha / hora Tampoco es bueno mirarlos, así que uso las marcas de tiempo cuando necesito una columna con la que no voy a hacer muchos cálculos, pero quiero una indicación de un vistazo.

La conversión a Julian y viceversa se puede hacer muy rápidamente en un buen idioma. Usando punteros, lo reduzco a aproximadamente 900 Clks (esto también es una conversión de un STRING a un INTEGER, por supuesto)

Cuando ingresa a aplicaciones serias que usan información de Fecha / Hora como, por ejemplo, los mercados financieros, las fechas julianas son de facto.

La consulta será como:

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

Da una cantidad de meses calendario desde la marca de fecha creada en un registro de cliente, permitiendo que MySQL haga la selección del mes internamente.

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

Ejecute este código y creará una función de diferencia de fecha que le dará la diferencia en el formato de fecha aaaa-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;

Esto depende de cómo desee que se defina el número de meses. Responda a estas preguntas: "¿Cuál es la diferencia en meses: 15 de febrero de 2008 - 12 de marzo de 2009". ¿Se define por un número claro de días que depende de los años bisiestos: qué mes es o el mismo día del mes anterior = 1 mes.

Un cálculo para días :

15 de febrero - > 29 (año bisiesto) = 14 1 de marzo de 2008 + 365 = 1 de marzo de 2009. 1 de marzo - > 12 de marzo = 12 días. 14 + 365 + 12 = 391 días. Total = 391 días / (días promedio en mes = 30) = 13.03333

Un cálculo de meses :

15 de febrero de 2008 - 15 de febrero de 2009 = 12 15 de febrero - > 12 de marzo = menos de 1 mes Total = 12 meses, o 13 si 15 de febrero - 12 de marzo se considera 'el mes pasado'

SELECT * 
FROM emp_salaryrevise_view 
WHERE curr_year Between '2008' AND '2009' 
    AND MNTH Between '12' AND '1'

Necesitaba un mes de diferencia con precisión. Aunque la solución de Zane Bien está en la dirección correcta, sus ejemplos segundo y tercero dan resultados inexactos. Un día en febrero dividido por la cantidad de días en febrero no es igual a un día en mayo dividido por la cantidad de días en mayo. Entonces, el segundo ejemplo debería mostrar ((31-5 + 1) / 31 + 13/30 =) 1.3043 y el tercer ejemplo ((29-27 + 1) / 29 + 2/30 + 3 =) 3.1701.

Terminé con la siguiente consulta:

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

Puede obtener años, meses y días de esta manera:

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

También puedes probar esto:

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

O

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

PERIOD_DIFF () función

Una de las formas es MySQL PERIOD_DIFF () que devuelve la diferencia entre dos períodos. Los períodos deben estar en el mismo formato, es decir, AAAAMM o AAMM. Cabe señalar que los períodos no son valores de fecha.

Código :

SELECT PERIOD_DIFF(200905,200811);

 ingrese la descripción de la imagen aquí

Respuesta simple dada la fecha de inicio como ins_frm y la fecha de finalización como 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

Disfruta :)))

Prueba esto

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

Esta consulta funcionó para mí :)

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

Simplemente toma dos fechas y recupera los valores entre ellas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top