Estoy buscando calcular el número 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?
mysql
date
datediff
date-arithmetic
Darryl Hein
fuente
fuente
PERIODDIFF
simplemente toma un valor YYYYMM, por lo que a menos que usted mismo tenga en cuenta los días antes de pasar los valores YYYYMM, todo lo que está calculando es el número de meses, redondeado al mes más cercano si hay menos de un número entero de meses. Vea la respuesta de Zane a continuación.PERIODDIFF
comentario? Perioddiff no toma valores de día, por lo que está calculando el número de meses redondeado al mes más cercano si hay menos de un número entero de mesesDiferencia de mes entre dos fechas determinadas:
Me sorprende que esto no se haya mencionado todavía:
Eche un vistazo al TIMESTAMPDIFF () en MySQL.
Lo que esto le permite hacer es pasar en dos
TIMESTAMP
oDATETIME
valores (o inclusoDATE
cuando MySQL se convertirá automáticamente), así como la unidad de tiempo en la que desea basar su diferencia.Puede especificar
MONTH
como 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 en cada mes (28, 30, 31) y también tiene en cuenta los años bisiestos; no tiene que preocuparse por nada de eso.
Diferencia de mes con precisión:
Es un poco más complicado si desea introducir precisión decimal en el número de meses transcurridos, pero así es como puede 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
yenddate
están 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
fuente
PERIODDIFF
comentario sobre la respuesta seleccionada son muy importantesPERIOD_DIFF calcula los 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;
fuente
También utilizo PERIODDIFF . Para obtener el año y el mes de la fecha, uso la función EXTRACCIÓN :
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;
fuente
DATE_FORMAT
método, ¡gracias! +1SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM FROM_UNIXTIME(time, "%Y%m%d"))) AS months FROM your_table;
PERIOD_DIFF
no toma valores de día, por lo que está calculando el número de meses redondeado al mes más cercano si hay menos de un número entero de meses. Debes editar tu respuesta para que quede claro.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 completo y exactamente 1 mes.
Para obtener la cantidad de meses enteros (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.
fuente
Del manual de MySQL:
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.
fuente
Prefiero esta forma, porque todos lo entenderán claramente a primera vista:
SELECT 12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months FROM tab;
fuente
¿Existe una forma mejor? si. No use marcas de tiempo de MySQL. Aparte del hecho de que ocupan 36 Bytes, no es nada cómodo trabajar con ellos. Recomendaría usar la fecha juliana y los segundos desde la medianoche para todos los valores de fecha / hora. Estos se pueden combinar para formar un 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
Es muy agradable trabajar con las fechas julianas cuando se realizan cálculos de fecha. Los valores de UNIXDateTime son buenos para trabajar cuando se realizan cálculos de fecha / hora. Ninguno de los dos es bueno para mirar, así que utilizo las marcas de tiempo cuando necesito una columna en la que no haré muchos cálculos con, 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 STRING a 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.
fuente
La consulta será como:
select period_diff(date_format(now(),"%Y%m"),date_format(created,"%Y%m")) from customers where..
Da un número de meses calendario desde la fecha de creación en el registro de un cliente, lo que permite que MySQL haga la selección del mes internamente.
fuente
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
fuente
Ejecute este código y creará una función datedeifference 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;
fuente
Esto depende de cómo desee que se defina el número de meses. Responda estas preguntas: '¿Cuál es la diferencia en meses: 15 de febrero de 2008 - 12 de marzo de 2009?'. ¿Está definido 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 de 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 / (promedio de días en el 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 del 15 de febrero al 12 de marzo se considera 'el último mes'
fuente
SELECT * FROM emp_salaryrevise_view WHERE curr_year Between '2008' AND '2009' AND MNTH Between '12' AND '1'
fuente
Necesitaba un mes de diferencia con precisión. Aunque la solución de Zane Bien va en la dirección correcta, su segundo y tercer ejemplo dan resultados inexactos. Un día de febrero dividido por el número de días de febrero no es igual a un día de mayo dividido por el número de días de mayo. Entonces, el segundo ejemplo debería dar como resultado ((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
fuente
Función PERIOD_DIFF ()
Una de las formas es MySQL PERIOD_DIFF () devuelve la diferencia entre dos períodos. Los períodos deben tener 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);
fuente
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
fuente
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;
fuente
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 :)))
fuente
Prueba esto
SELECT YEAR(end_date)*12 + MONTH(end_date) - (YEAR(start_date)*12 + MONTH(start_date))
fuente
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.
fuente