sql >> Base de Datos >  >> RDS >> PostgreSQL

Averiguar el número de meses entre 2 fechas

La expresión

age('2012-11-30 00:00:00'::timestamp, '2012-10-31 00:00:00'::timestamp) 

da 30 days . Esperamos 1 month ya que ambos valores apuntan a los últimos días del mes. Si agregamos 1 día a los valores, obtendremos los primeros días del próximo mes y

age('2012-12-01 00:00:00'::timestamp, '2012-11-01 00:00:00'::timestamp)

nos dará 1 mes como se esperaba. Entonces, verifiquemos si tenemos dos últimos días del mes y, en este caso, devolvamos el intervalo de edad de los próximos días. En otros casos, devolveremos el intervalo de edad de los valores originales:

create or replace function age_m (t1 timestamp, t2 timestamp)
returns interval language plpgsql immutable
as $$
declare
    _t1 timestamp = t1+ interval '1 day';
    _t2 timestamp = t2+ interval '1 day';
begin
    if extract(day from _t1) = 1 and extract(day from _t2) = 1 then
        return age(_t1, _t2);
    else
        return age(t1, t2);
    end if;
end $$;

Algunos ejemplos:

with my_table(date1, date2) as (
values
    ('2012-11-30 00:00:00'::timestamp, '2012-10-31 00:00:00'::timestamp),
    ('2012-12-31 00:00:00'::timestamp, '2012-10-31 00:00:00'::timestamp),
    ('2013-01-31 00:00:00'::timestamp, '2012-10-31 00:00:00'::timestamp),
    ('2013-02-28 00:00:00'::timestamp, '2012-10-31 00:00:00'::timestamp)
)

select *, age(date1, date2), age_m(date1, date2)
from my_table

        date1        |        date2        |      age       | age_m  
---------------------+---------------------+----------------+--------
 2012-11-30 00:00:00 | 2012-10-31 00:00:00 | 30 days        | 1 mon
 2012-12-31 00:00:00 | 2012-10-31 00:00:00 | 2 mons         | 2 mons
 2013-01-31 00:00:00 | 2012-10-31 00:00:00 | 3 mons         | 3 mons
 2013-02-28 00:00:00 | 2012-10-31 00:00:00 | 3 mons 28 days | 4 mons
(4 rows)