Je cherche un moyen d'implémenter la SQLServer-function de datiff dans PostgreSQL. C'est,
Cette fonction renvoie le nombre (en tant que valeur entière signée) des limites de datePart spécifié spécifiées croisées entre les dates de début et de fin spécifiées.
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 une soustraction, mais avez-vous une idée des deux autres?
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'));
Ces fonctions vous donneront plein années, mois, jours ... entre deux dates. Pour le nombre de changements de date, utilisez le lien fourni par revoua: http://www.sqlines.com/postgresql/how-to/datediff
il suffit de les soustraire:
select '2015-01-12'::date - '2015-01-01'::date;
Cela vous donnera:
?column?
----------
11
Presque la même fonction que vous aviez besoin (basé sur la réponse d’atiruz, version abrégée de UDF à partir de ici )
CREATE OR REPLACE FUNCTION datediff(type VARCHAR, date_from DATE, date_to DATE) RETURNS INTEGER LANGUAGE plpgsql
AS
$$
DECLARE age INTERVAL;
BEGIN
CASE type
WHEN 'year' THEN
RETURN date_part('year', date_to) - date_part('year', date_from);
WHEN 'month' THEN
age := age(date_to, date_from);
RETURN date_part('year', age) * 12 + date_part('month', age);
ELSE
RETURN (date_to - date_from)::int;
END CASE;
END;
$$;
Usage:
/* Get months count between two dates */
SELECT datediff('month', '2015-02-14'::date, '2016-01-03'::date);
/* Result: 10 */
/* Get years count between two dates */
SELECT datediff('year', '2015-02-14'::date, '2016-01-03'::date);
/* Result: 1 */
/* Get days count between two dates */
SELECT datediff('day', '2015-02-14'::date, '2016-01-03'::date);
/* Result: 323 */
/* Get months count between specified and current date */
SELECT datediff('month', '2015-02-14'::date, NOW()::date);
/* Result: 47 */
SELECT date_part ('year', f) * 12
+ date_part ('month', f)
FROM age ('2015-06-12'::DATE, '2014-12-01'::DATE) f
Résultat: 6
Je voudrais développer la réponse de Riki_tiki_tavi et obtenir les données. J'ai créé une fonction de date qui fait presque tout ce que le serveur SQL fait. Ainsi, nous pouvons prendre en compte n’importe quelle unité.
create function datediff(units character varying, start_t timestamp without time zone, end_t timestamp without time zone) returns integer
language plpgsql
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;
$$;
Voici un exemple complet avec sortie. psql (10.1, serveur 9.5.10).
Vous obtenez 58, pas une valeur inférieure à 30.
Supprimer la fonction age (), a résolu le problème mentionné dans un précédent article.
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
Cette question est pleine de malentendus. Tout d'abord, permet de bien comprendre la question. Le demandeur souhaite obtenir le même résultat que lors de l'exécution de la fonction MS SQL ServerDATEDIFF ( datepart , startdate , enddate )
où datepart
prend dd
, mm
ou yy
.
Cette fonction est définie par:
Cette fonction renvoie le nombre (en tant que valeur entière signée) des limites de datePart spécifié spécifiées croisées entre les dates de début et de fin spécifiées.
Cela signifie combien de jours, de mois ou d’années sont franchis. Pas combien de jours, mois ou années c'est entre eux. C’est pourquoi datediff(yy, '2010-04-01', '2012-03-05')
est égal à 2 et non à 1. Il y a moins de 2 ans entre ces dates, ce qui signifie qu’une année entière est écoulée, mais que deux années se sont écoulées, de 2010 à 2011 et de 2011 à 2012.
Voici ma meilleure tentative pour reproduire correctement la logique.
-- datediff(dd`, '2010-04-01', '2012-03-05') = 704 // 704 changes of day in this interval
select ('2012-03-05'::date - '2010-04-01'::date );
-- 704 changes of day
-- datediff(mm, '2010-04-01', '2012-03-05') = 23 // 23 changes of month
select (date_part('year', '2012-03-05'::date) - date_part('year', '2010-04-01'::date)) * 12 + date_part('month', '2012-03-05'::date) - date_part('month', '2010-04-01'::date)
-- 23 changes of month
-- datediff(yy, '2010-04-01', '2012-03-05') = 2 // 2 changes of year
select date_part('year', '2012-03-05'::date) - date_part('year', '2010-04-01'::date);
-- 2 changes of year