PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Finden Sie die Anzahl der Monate zwischen 2 Daten heraus

Der Ausdruck

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

ergibt 30 days . Wir erwarten 1 month da beide Werte auf die letzten Tage des Monats zeigen. Wenn wir 1 Tag zu den Werten hinzufügen, erhalten wir die ersten Tage des nächsten Monats und

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

wird uns wie erwartet 1 Monat geben. Lassen Sie uns also prüfen, ob wir zwei letzte Tage des Monats haben und in diesem Fall das Altersintervall der nächsten Tage zurückgeben. In anderen Fällen geben wir das Altersintervall der ursprünglichen Werte zurück:

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 $$;

Einige Beispiele:

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)