PostgreSQL
La base de données la plus sophistiquée au monde.

Ouverture de session

Navigation

Contactez-nous

Administration du site :
"equipe chez postgresqlfr point org"

Contact presse :
"fr chez postgresql point org"

Contact association :
"bureau chez postgresqlfr point org"

Questions PostgreSQL :
 IRC :
  serveur irc.freenode.net
  canal #postgresqlfr

Recherche

Accéder aux archives

« Octobre 2008  
Lun Mar Mer Jeu Ven Sam Dim
  2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31  

Syndication

Flux XML

Sondage

Quelle est la version de PostgreSQL la plus répandue sur vos serveurs ?
8.3
10%
8.2
42%
8.1
40%
8.0
2%
7.4
6%
7.3 ou antérieure
0%
Nombre de votes: 48

Nombre de semaines entre deux dates quelconques

| Nombre de semaines entre deux dates quelconques

Par dim le 28/11/2007 - 19:33

Cette fois-ci il s'agit donc de trouver le nombre de semaines entre deux dates quelconques. Ce qui rend la solution un poil compliquée, c'est que toutes les années n'ont pas le même nombre de semaines (52*7 ça donne que 364 jours).

On va donc faire ça en deux temps, d'abord trouver le nombre de semaines de chaque année faisant partie de l'intervalle, ensuite c'est facile.

Déjà, trouver les années comprises entre deux dates, ainsi que le premier janvier de l'année suivante :

dim# select year, to_date(year+1, 'YYYY-01-01') as d
 from generate_series(extract(year from (current_date - interval '4 years')::date)::int,
          extract(year from current_date)::int) as year;
 year | d
------+------------
 2003 | 01-01-2004
 2004 | 01-01-2005
 2005 | 01-01-2006
 2006 | 01-01-2007
 2007 | 01-01-2008
(5 lignes)

Maintenant, première ruse : si le premier janvier de l'année suivante est semaine 1, alors l'année donnée contient 52 semaines, sinon elle contient le nombre de semaine correspondant au numéro de semaine du premier janvier de l'année suivante :

dim=# select extract(year from d) - 1 as year,
dim-# case when extract(week from d) = 1
dim-# then extract(week from d - interval '1 week')
dim-# else extract(week from d) end as nb_weeks
dim-# from (
dim(# select year, to_date(year+1, 'YYYY-01-01') as d
dim(# from generate_series(extract(year from (current_date - interval '4 years')::date)::int,
dim(# extract(year from current_date)::int) as year) as x;
 year | nb_weeks
------+----------
 2003 | 52
 2004 | 53
 2005 | 52
 2006 | 52
 2007 | 52
(5 lignes)

Il reste à additionner toutes les semaines des années intermédiaires et à ajouter le numéro de semaine de l'année courante pour avoir le nombre de semaines depuis le premier janvier de l'année de la date de début. On enlèvera donc de cette somme le numéro de semaine de la date de début pour avoir notre résultat :

create or replace function weeks(timestamp, timestamp) returns int language sql
as $$
  select extract(week from $2)::int
  +
  coalesce(
   sum( case when extract(week from d) = 1
    then extract(week from d - interval '1 week')
    else extract(week from d) end ),
   0)::int
   -
   extract(week from $1)::int
  from (
   select year, to_date(year+1, 'YYYY-01-01') as d
   from generate_series(extract(year from $1)::int,
    extract(year from $2)::int - 1) as year
   ) as x;
$$;
 
dim=# select weeks(current_date - interval '18 months', current_date);
 weeks
-------
   79
(1 ligne)
 
dim=# select weeks(current_date - interval '4 years', current_date);
 weeks
-------
   209
(1 ligne)

Et voilĂ  :)

Note : on utilise COALESCE() sur le SUM() afin de savoir compter le nombre de semaines entre deux dates de la même année aussi !

Options d'affichage des commentaires

Sélectionnez la méthode d'affichage des commentaires que vous préférez, puis cliquez sur "Sauvegarder les paramètres" pour activer vos changements.

La fonction weeks ne fonction

Sebastien Lardiere/ = 28 Novembre, 2007 - 20:13

La fonction weeks ne fonctionne pas sur une 8.3 à cause du to_date, dont les arguments ne sont pas corrects et/ou pas assez explicite. Voici la meme fonction corrigée :

create or replace function weeks(timestamp, timestamp) returns int language sql
as $$
select extract(week from $2)::int
+
coalesce(
sum( case when extract(week from d) = 1
then extract(week from d - interval '1 week')
else extract(week from d) end ),
0)::int
-
extract(week from $1)::int
from (
select year, to_date((year+1)::text, 'YYYY'::text) as d
from generate_series(extract(year from $1)::int,
extract(year from $2)::int - 1) as year
) as x;
$$;

Ensuite, je n'obtient pas le meme resultat que toi sur la première requete, il peut y avoir un probleme avec les locales ...

--
Sébastien Lardière


© PostgreSQLFr, tous droits rĂ©servĂ©s.
Site déclaré à la CNIL sous le numéro 1074678, conformément à la Loi en vigueur.