2013-01-10 19 views
10

In Oracle kann ich herausfinden, Nein: Monate zwischen der Verwendung von MONTHS_BETWEEN-Funktion.Monate zwischen zwei Daten Funktion

In Postgres verwende ich Extrakt-Funktion für diese. eg.like

select 
    extract(year from age(current_date, '2012-12-09')) * 12 
    + 
    extract(month from age(current_date, '2012-12-09')) 

Gibt es noch andere Möglichkeiten (in Funktionen eingebaut) in Postgres ??

+0

sogar benutzte ich die gleiche Art und Weise –

Antwort

3

Leider scheint es nicht, denn extract(month ...) gibt die Anzahl der Monate zurück modulo 12.

Es gibt eine kleine Vereinfachung, die Sie vornehmen können; Entfernen Sie den ersten Parameter von age() - ist die Standard Alter von current_date, so dass diese beiden sind äquivalent:

age(current_date, '2012-12-09') 
age('2012-12-09') 
+0

'Alter ('2012.12.09')' einen Fehler (postgresql 9.2.1) aufgrund der unbekannten Argument Typ erzeugen. Sie müssen angeben: age ('2012-12-09' :: date) ' – araqnid

1

Sie können UDF verwenden, z.B. Ich habe die here folgende gefunden:

CREATE OR REPLACE FUNCTION DateDiff (units VARCHAR(30), start_t TIMESTAMP, end_t TIMESTAMP) 
    RETURNS INT AS $$ 
    DECLARE 
    diff_interval INTERVAL; 
    diff INT = 0; 
    years_diff INT = 0; 
    BEGIN 
    IF units IN ('yy', 'yyyy', 'year', 'mm', 'm', 'month') THEN 
     years_diff = DATE_PART('year', end_t) - DATE_PART('year', start_t); 

     IF units IN ('yy', 'yyyy', 'year') THEN 
     -- SQL Server does not count full years passed (only difference between year parts) 
     RETURN years_diff; 
     ELSE 
     -- If end month is less than start month it will subtracted 
     RETURN years_diff * 12 + (DATE_PART('month', end_t) - DATE_PART('month', start_t)); 
     END IF; 
    END IF; 

    -- Minus operator returns interval 'DDD days HH:MI:SS' 
    diff_interval = end_t - start_t; 

    diff = diff + DATE_PART('day', diff_interval); 

    IF units IN ('wk', 'ww', 'week') THEN 
     diff = diff/7; 
     RETURN diff; 
    END IF; 

    IF units IN ('dd', 'd', 'day') THEN 
     RETURN diff; 
    END IF; 

    diff = diff * 24 + DATE_PART('hour', diff_interval); 

    IF units IN ('hh', 'hour') THEN 
     RETURN diff; 
    END IF; 

    diff = diff * 60 + DATE_PART('minute', diff_interval); 

    IF units IN ('mi', 'n', 'minute') THEN 
     RETURN diff; 
    END IF; 

    diff = diff * 60 + DATE_PART('second', diff_interval); 

    RETURN diff; 
    END; 
    $$ LANGUAGE plpgsql; 
+0

Ich habe kürzlich mit einem neuen Entwickler gearbeitet, der diese Funktion in unsere Datenbanken aufgenommen hat, um einige Aufgaben zu erledigen, und ich kann bezeugen, dass SUCKS extrem langsam ist, nicht optimiert, das performing ist so schlecht. Es kann vielseitig sein, ist aber keine gute Lösung. Probieren Sie einfach diesen einfachen Vergleich: Alter (Geburtsdatum) gegen diese Funktion. – FiruzzZ

10

Das ist einfach in PostgreSQL neu zu implementieren nur SQL-Funktionen verwenden, um aufzuräumen, was du schon hast:

create function months_of(interval) 
returns int strict immutable language sql as $$ 
    select extract(years from $1)::int * 12 + extract(month from $1)::int 
$$; 

create function months_between(date, date) 
returns int strict immutable language sql as $$ 
    select abs(months_of(age($1, $2))) 
$$; 

Und jetzt select months_between('1978-06-20', '2011-12-09') produziert 401 .

+6

"Monat" ist ein unscharfer Begriff, und leider wird es nicht weniger unscharf, wenn Sie eine Funktion darum herum umschließen. Die Verwendung von 'monates_between ('2012-01-01', '2012-01-31') gibt 0 für dieses 30-Tage-Intervall zurück. Aber die Verwendung von 'monates_between ('2012-02-01', '2012-03-01')' gibt 1 für dieses 29-Tage-Intervall zurück. Die kurze Geschichte ist, dass Sie * definieren sollten, was "Monat" in Ihrer Anwendung bedeutet, bevor Sie anfangen, Code zu schreiben. –

+1

@Catcall Ihr Kommentar ist ziemlich gültig, aber sollte es nicht auf das OP gerichtet sein? Der Code von araqnid verhält sich genau so wie der Code des OPs. Ich nehme an, das ist was er will. –

+4

Ich weiß es nicht. Ich habe Araqnids Antwort aufgewertet. Meiner Erfahrung nach denken die meisten Leute, die solche Funktionen benutzen * nicht darüber nach, was * Monat * oder * Wochennummer * in ihrer Anwendung bedeuten sollte. Sie benutzen einfach alles, was sie finden. (Das ist eine Beobachtung, keine Kritik.) Das OP hat keine Antwort akzeptiert, also erwarte ich, dass er oder sie all diese Dinge früher oder später liest. Vielleicht bin ich unrealistisch optimistisch. –

0
SELECT date_part ('year', f) * 12 
     + date_part ('month', f) 
FROM age (CURRENT_DATE, '2014-12-01') f 
Verwandte Themen