PostgreSQL: jours / mois / années entre deux dates

Je cherche un moyen d'implémenter la fonction SQLServer datediff dans PostgreSQL. C'est-à-dire

datediff(dd, '2010-04-01', '2012-03-05') = 704 // 704 changes of day in this interval
datediff(mm, '2010-04-01', '2012-03-05') = 23  // 23 changes of month
datediff(yy, '2010-04-01', '2012-03-05') = 2   // 2 changes of year

Je sais que je pourrais faire ' dd ' en utilisant simplement la soustraction,mais une idée sur les deux autres?

47
demandé sur ozczecho 2013-07-24 15:49:45

6 réponses

Essayez quelque chose comme:

select age('2010-04-01', '2012-03-05'),
       date_part('year',age('2010-04-01', '2012-03-05')),
       date_part('month',age('2010-04-01', '2012-03-05')),
       date_part('day',age('2010-04-01', '2012-03-05'));

Cette fonction vous donnera complète années, mois, jours ... entre les deux dates. Pour le nombre de changements de date - nous le lien fourni par revoua : http://www.sqlines.com/postgresql/how-to/datediff

83
répondu Igor Romanchenko 2013-07-24 12:05:00

Soustrayez-les simplement:

select '2015-01-12'::date - '2015-01-01'::date;

Cela vous donnera:

?column? 
----------
   11
64
répondu mehdi 2015-06-12 09:38:56

J'ai passé du temps à chercher la meilleure réponse, et je pense que je l'ai.

Ce sql vous donnera le nombre de jours entre deux dates integer:

SELECT
    (EXTRACT(epoch from age('2017-6-15', now())) / 86400)::int

..qui, lorsqu'il est exécuté aujourd'hui (2017-3-28) me donne:

?column?
------------
77

L'idée fausse sur la réponse acceptée:

select age('2010-04-01', '2012-03-05'),
   date_part('year',age('2010-04-01', '2012-03-05')),
   date_part('month',age('2010-04-01', '2012-03-05')),
   date_part('day',age('2010-04-01', '2012-03-05'));

.. est-ce que vous obtiendrez la différence littérale entre les parties des chaînes de date, pas le temps entre les deux dates.

I. E:

Age(interval)=-1 years -11 mons -4 days;

Years(double precision)=-1;

Months(double precision)=-11;

Days(double precision)=-4;

23
répondu WebWanderer 2017-06-21 15:34:52

Presque la même fonction que vous aviez besoin (basé sur la réponse d'atiruz, version raccourcie D'UDF de ici)

CREATE OR REPLACE FUNCTION datediff(type VARCHAR, date_from DATE, date_to DATE) RETURNS INTEGER LANGUAGE plpgsql
AS
$$
DECLARE age INTERVAL;
BEGIN
    age := age(date_to, date_from);
    CASE type
        WHEN 'month' THEN
            RETURN date_part('year', age) * 12 + date_part('month', age);
        WHEN 'year' THEN
            RETURN date_part('year', age);
        ELSE
            RETURN (date_to - date_from)::int;
    END CASE;
END;
$$;

Utilisation:

/* Get months count between two dates */
SELECT datediff('month', '2015-02-14', '2016-01-03');

/* Get complete years count between two dates */
SELECT datediff('year', '2015-02-14', '2016-01-03');

/* Get days count between two dates */
SELECT datediff('day', '2015-02-14', '2016-01-03');

/* Get months count between specified and current date */
SELECT datediff('month', '2015-02-14', NOW()::date);
9
répondu Riki_tiki_tavi 2016-01-26 05:47:53
SELECT date_part ('year', f) * 12
     + date_part ('month', f)
FROM age ('2015-06-12'::DATE, '2014-12-01'::DATE) f

Résultat: 6

6
répondu atiruz 2015-06-12 18:17:57

Voici un exemple complet avec la sortie. psql (10.1, serveur 9.5.10).

Vous obtenez 58, pas une valeur inférieure à 30.
Supprimer la fonction age (), résolu le problème que le post précédent mentionné.

drop table t;
create table t(
    d1 date
);

insert into t values(current_date - interval '58 day');

select d1
, current_timestamp - d1::timestamp date_diff
, date_part('day', current_timestamp - d1::timestamp)
from t;

     d1     |        date_diff        | date_part
------------+-------------------------+-----------
 2018-05-21 | 58 days 21:41:07.992731 |        58
0
répondu Charlie 木匠 2018-07-18 21:45:53