Obtenir la liste des dates dans une plage dans PostgreSQL

J’aimerais avoir la liste des jours entre les deux dates (y compris les dates) dans une firebase database PostgreSQL . Par exemple, si j’avais:

  • date de début: 29 juin 2012
  • date de fin: 3 juillet 2012

alors le résultat devrait être:

29 june 2012 30 june 2012 1 july 2012 2 july 2012 3 july 2012 

Quelle serait la meilleure façon de le faire dans PostgreSQL?

Merci.

 select CURRENT_DATE + i from generate_series(date '2012-06-29'- CURRENT_DATE, date '2012-07-03' - CURRENT_DATE ) i 

ou même plus court:

 select i::date from generate_series('2012-06-29', '2012-07-03', '1 day'::interval) i 

Comme timestamp :

 select generate_series('2012-06-29', '2012-07-03', '1 day'::interval); generate_series ------------------------ 2012-06-29 00:00:00-03 2012-06-30 00:00:00-03 2012-07-01 00:00:00-03 2012-07-02 00:00:00-03 2012-07-03 00:00:00-03 

ou coulé à date :

 select (generate_series('2012-06-29', '2012-07-03', '1 day'::interval))::date; generate_series ----------------- 2012-06-29 2012-06-30 2012-07-01 2012-07-02 2012-07-03 

Cela devrait le faire:

 select date '2012-06-29' + i from generate_series(1, (select date '2012-07-3' - date '2012-06-29')) i 

Si vous ne voulez pas répéter la date de début dans la sous-sélection, les choses se compliquent un peu:

 with min_max (start_date, end_date) as ( values (date '2012-06-29', date '2012-07-3') ), date_range as ( select end_date - start_date as duration from min_max ) select start_date + i from min_max cross join generate_series(1, (select duration from date_range)) i; 

(Voir la réponse de maniek pour une version bien meilleure du problème “no-repeat”)

Pour des choses comme celle-ci, il est généralement utile d’avoir un tableau de dates dans le système.

Tout comme une table de nombres, ils peuvent être très utiles et plus rapides à utiliser que la génération des dates à la volée, en particulier lorsque vous utilisez des ensembles de données volumineux.

Un tel tableau de dates de 1900 à 2100 sera très petit, donc il n’ya pas beaucoup de stockage en réserve.

Edit: Ne sais pas pourquoi cela est voté, ce sera probablement le meilleur pour la performance. De plus, il a tant d’autres avantages. Vous souhaitez lier les commandes à un nombre de performances sortingmessortingel? C’est un lien simple entre les tables. (Order.OrderDate -> Dates.Date -> Dates.Quarter -> PerformanceTotal.Quarter) etc. C’est la même chose pour traiter les jours ouvrables, comme le dernier jour ouvrable d’un mois ou le premier mardi du mois précédent. Comme une table de nombres, je les recommande fortement!

 select generate_series('2012-06-29', '2012-07-03', '1 day'::interval)::date; 

Si vous avez déjà une firebase database que vous souhaitez interroger:

 SELECT TO_CHAR(date_column,'DD Mon YYYY') FROM some_table WHERE date_column BETWEEN '29 Jun 2012' AND '3 JUL 2012' GROUP BY date_column ORDER BY date_column 

Cela se traduira par:

 "29 Jun 2012" "30 Jun 2012" "01 Jul 2012" "02 Jul 2012" "03 Jul 2012" 

Si la plage de dates doit provenir d’une expression de table, vous pouvez utiliser la construction suivante:

 DROP TABLE tbl ; CREATE TABLE tbl (zdate date NOT NULL ); INSERT INTO tbl(zdate) VALUES( '2012-07-01') , ('2012-07-09' ); WITH mima AS ( SELECT MIN(zdate)::timestamp as mi , MAX(zdate)::timestamp as ma FROM tbl ) SELECT generate_series( mima.mi, mima.ma, '1 day':: interval):: date FROM mima ; 

Les moulages sont nécessaires car generate_series () ne prend pas d’argument de date.

Cette fonction PLpg / SQL ferait l’affaire:

 CREATE OR REPLACE FUNCTION getDateList(date1 date, date2 date) RETURNS SETOF date AS $BODY$ DECLARE count integer; lower_limit integer := 0; upper_limit integer := date2 - date1; BEGIN FOR count IN lower_limit..upper_limit LOOP RETURN NEXT date1 + count; END LOOP; RETURN; END; $BODY$ LANGUAGE plpgsql VOLATILE