Pour générer une série de dates, c'est la manière optimale :
SELECT t.day::date
FROM generate_series(timestamp '2004-03-07'
, timestamp '2004-08-16'
, interval '1 day') AS t(day);
Aucun supplément date_trunc()n'est nécessaire. Le cast to date( day::date) fait cela implicitement.
Mais il est également inutile de convertir des littéraux de date dateen paramètre d'entrée. Au contraire, timestampc'est le meilleur choix . L'avantage en termes de performances est faible, mais il n'y a aucune raison de ne pas en profiter. Et vous n'impliquez pas inutilement des règles DST (heure d'été) associées à la conversion de datevers timestamp with time zoneet inversement. Voir ci-dessous.
Syntaxe courte équivalente, moins explicite:
SELECT day::date
FROM generate_series(timestamp '2004-03-07', '2004-08-16', '1 day') day;
Ou avec la fonction de retour de set dans la SELECTliste:
SELECT generate_series(timestamp '2004-03-07', '2004-08-16', '1 day')::date AS day;
Le ASmot-clé est obligatoire dans la dernière variante, Postgres interpréterait mal l'alias de colonne daysinon. Et je ne conseillerais pas cette variante avant Postgres 10 - du moins pas avec plus d'une fonction de retour d'ensemble dans la même SELECTliste:
(Cela mis à part, la dernière variante est généralement la plus rapide par une petite marge.)
Pourquoi timestamp [without time zone]?
Il existe un certain nombre de variantes surchargées de generate_series(). Actuellement (Postgres 11):
SELECT oid::regprocedure AS function_signature
, prorettype::regtype AS return_type
FROM pg_proc
where proname = 'generate_series';
function_signature | return_type
: ------------------------------------------------- ------------------------------- | : --------------------------
generate_series (entier, entier, entier) | entier
generate_series (entier, entier) | entier
generate_series (bigint, bigint, bigint) | bigint
generate_series (bigint, bigint) | bigint
generate_series (numérique, numérique, numérique) | numérique
generate_series (numérique, numérique) | numérique
generate_series (horodatage sans fuseau horaire, horodatage sans fuseau horaire, intervalle) | horodatage sans fuseau horaire
generate_series (horodatage avec fuseau horaire, horodatage avec fuseau horaire, intervalle) | horodatage avec fuseau horaire
(Des numericvariantes ont été ajoutées avec Postgres 9.5.) Les plus pertinentes sont les deux dernières en gras prenant et retournant timestamp/ timestamptz.
Il n'y a pas de variante prise ou retourdate . Un cast explicite est nécessaire pour revenir date. L'appel avec des timestamparguments résout directement la meilleure variante sans descendre dans les règles de résolution de type de fonction et sans conversion supplémentaire pour l'entrée.
timestamp '2004-03-07'est parfaitement valide, btw. La partie de temps omise est par défaut au 00:00format ISO.
Grâce à la résolution du type de fonction, nous pouvons encore passer date. Mais cela nécessite plus de travail de la part de Postgres. Il y a un cast implicite de dateà timestampet un de dateà timestamptz. Serait ambigu, mais timestamptzest "préféré" parmi les "types de date / heure". Le match est donc décidé à l'étape 4d. :
Parcourez tous les candidats et conservez ceux qui acceptent les types préférés (de la catégorie de type du type de données d'entrée) dans la plupart des positions où la conversion de type sera requise. Conservez tous les candidats si aucun n'accepte les types préférés. S'il ne reste qu'un seul candidat, utilisez-le; sinon, passez à l'étape suivante.
En plus du travail supplémentaire dans la résolution des types de fonction, cela ajoute une conversion supplémentaire timestamptz- ce qui non seulement ajoute plus de coûts, mais peut également introduire des problèmes avec DST conduisant à des résultats inattendus dans de rares cas. (L'heure d'été est un concept idiot, d'ailleurs, je ne saurais trop insister sur ce point.)
J'ai ajouté des démos au violon montrant le plan de requête le plus cher:
db <> violon ici
En relation: