Discussion:
requête tenant compte des jours ouvrés
(trop ancien pour répondre)
Jean-Paul Witz
2006-10-22 03:25:48 UTC
Permalink
Bonjour

Dans un table, j'ai deux champs: date et duree (en jours).
Je voudrais faire une requête select qui, dans la clause where,
sélectionne les dates+duree inférieure ou égal à aujourd'hui en tenant
compte des jours ouvrés. Exemple:
Aujourd'hui, nous sommes le dimanche 2006-10-22
si date contient 2006-10-20(c'est un jeudi) et duree contient 1,
l'enregistrement ne doit pas être sélectionné
par contre date contient 2006-10-21(c'est un vendredi) et duree contient
1, l'enregistrement doit être sélectionné, car, jours ouvrés,
vendredi+1=lundi.
Est-il posssible de faire ceci dans une requête Mysql?

Merci

JPW
Antoun
2006-10-22 03:43:25 UTC
Permalink
Post by Jean-Paul Witz
Bonjour
Dans un table, j'ai deux champs: date et duree (en jours).
Je voudrais faire une requête select qui, dans la clause where,
sélectionne les dates+duree inférieure ou égal à aujourd'hui en tenant
Aujourd'hui, nous sommes le dimanche 2006-10-22
si date contient 2006-10-20(c'est un jeudi) et duree contient 1,
l'enregistrement ne doit pas être sélectionné
par contre date contient 2006-10-21(c'est un vendredi) et duree contient
1, l'enregistrement doit être sélectionné, car, jours ouvrés,
vendredi+1=lundi.
Est-il posssible de faire ceci dans une requête Mysql?
ton calcul vendredi + 1 = lundi se fait avec un CASE WHEN :

...
WHERE CASE WEEKDAY(madate + INTERVAL maduree DAY)
WHEN 5 THEN madate + INTERVAL (maduree + 2) DAY -- samedi => lundi
WHEN 6 THEN madate + INTERVAL (maduree + 1) DAY -- dimanche => lundi
ELSE madate + INTERVAL maduree DAY -- cas normal
END <= CURDATE()

Cette formule suppose que maduree est toujours inférieure ou égale à 7,
càd qu'il n'y a au plus qu'un week-end à sauter. Si ce n'est pas le cas,
il faut la compliquer un peu en ajoutant deux jours tous les cinq jours
pleins.
--
Antoun

Guide complet MySQL 5, par Antoine Dinimant, éd. MicroApplication
http://www.microapp.com/livre_mysql_7873.html
helios
2006-10-22 09:37:25 UTC
Permalink
Post by Antoun
Post by Jean-Paul Witz
Bonjour
Dans un table, j'ai deux champs: date et duree (en jours).
Je voudrais faire une requête select qui, dans la clause where,
sélectionne les dates+duree inférieure ou égal à aujourd'hui en tenant
Aujourd'hui, nous sommes le dimanche 2006-10-22
si date contient 2006-10-20(c'est un jeudi) et duree contient 1,
l'enregistrement ne doit pas être sélectionné
par contre date contient 2006-10-21(c'est un vendredi) et duree contient
1, l'enregistrement doit être sélectionné, car, jours ouvrés,
vendredi+1=lundi.
Est-il posssible de faire ceci dans une requête Mysql?
...
WHERE CASE WEEKDAY(madate + INTERVAL maduree DAY)
WHEN 5 THEN madate + INTERVAL (maduree + 2) DAY -- samedi => lundi
WHEN 6 THEN madate + INTERVAL (maduree + 1) DAY -- dimanche => lundi
ELSE madate + INTERVAL maduree DAY -- cas normal
END <= CURDATE()
Cette formule suppose que maduree est toujours inférieure ou égale à 7,
càd qu'il n'y a au plus qu'un week-end à sauter. Si ce n'est pas le cas,
il faut la compliquer un peu en ajoutant deux jours tous les cinq jours
pleins.
--
Antoun
Guide complet MySQL 5, par Antoine Dinimant, éd. MicroApplication
http://www.microapp.com/livre_mysql_7873.html
jour ouvré ou ouvrable ?
le lundi de Paque marche comment dans ce cas ?
le jeudi ascension ?
Jean-Paul Witz
2006-10-22 16:27:20 UTC
Permalink
Merci pour cette piste.
Mais en réalité mon pb est plus complexe. Je vous le soumets:
Je connais la date de début (madate) et la durée en 1/2 journées (maduree).
La requête mysql doit définir la date de fin en ne tenant compte ni des
mercredis, ni des samedi après-midis, ni des dimanches.

Existe-t-il une solution?

Merci de votre aide.

JPW
Antoun
2006-10-22 16:37:43 UTC
Permalink
Post by Jean-Paul Witz
Merci pour cette piste.
Je connais la date de début (madate) et la durée en 1/2 journées (maduree).
comment modélises-tu la notion de demi-journée dans madate ? (par
exemple, une façon de modéliser serait que 2006-10-23 00:00:00
représente le lundi matin et 2006-10-23 12:00:00 représente le lundi
après-midi)
Post by Jean-Paul Witz
La requête mysql doit définir la date de fin en ne tenant compte ni des
mercredis, ni des samedi après-midis, ni des dimanches.
faut-il tenir compte des jours fériés ?

maduree peut-elle dépasser une semaine (14 demi-journées)
Post by Jean-Paul Witz
Existe-t-il une solution?
il y en a plusieurs, le choix dépend de tes réponses aux questions ci-dessus
--
Antoun

Guide complet MySQL 5, par Antoine Dinimant, éd. MicroApplication
http://www.microapp.com/livre_mysql_7873.html
Jean-Paul Witz
2006-10-23 17:01:55 UTC
Permalink
Post by Antoun
Post by Jean-Paul Witz
Merci pour cette piste.
Je connais la date de début (madate) et la durée en 1/2 journées (maduree).
comment modélises-tu la notion de demi-journée dans madate ? (par
exemple, une façon de modéliser serait que 2006-10-23 00:00:00
représente le lundi matin et 2006-10-23 12:00:00 représente le lundi
après-midi)
Oui, c'est tout à fait cela.
Post by Antoun
Post by Jean-Paul Witz
La requête mysql doit définir la date de fin en ne tenant compte ni
des mercredis, ni des samedi après-midis, ni des dimanches.
faut-il tenir compte des jours fériés ?
Oui si cela est possible. J'ai pensé que c'était impossible, c'est pour
pour ça que je ne l'ai pas évoqué.
Post by Antoun
maduree peut-elle dépasser une semaine (14 demi-journées)
Oui, cela peut durer plusieurs semaines
Post by Antoun
Post by Jean-Paul Witz
Existe-t-il une solution?
il y en a plusieurs, le choix dépend de tes réponses aux questions ci-dessus
Une seule me suffirait! Si ça marche, je vous tire mon chapeau, à vous
et à mysql!

JPW
Antoun
2006-10-23 22:36:28 UTC
Permalink
Si tu veux tenir compte des jours fériés, il n'y a pas d'autre choix que
de passer par une table calendrier.

Il y a diverses façon de le faire, l'une des plus simples consiste à n'y
mettre que les demi-journées ouvrées, et à les numéroter :


DemiJournee Num
===========================
2006-10-23 00:00:00 50
2006-10-23 12:00:00 51
2006-10-24 00:00:00 52
2006-10-24 12:00:00 53
2006-10-25 12:00:00 54
...

Voici par exemple une requête affichant TableX.madate, TableX.maduree,
et madate + maduree :

SELECT T.madate, T.maduree, C2.DemiJournee AS Addition
FROM TableX T
INNER JOIN Calendrier C1 ON T.madate = C.DemiJournee
INNER JOIN Calendrier C2 ON C2.Num = C1.Num + T.maduree

C1 permet de traduite madate en Num ; C2 permet de calculer le décalage
et de traduire le résultat en date.

Cette solution pose deux difficultés :

1/ comment constituer la table calendrier
2/ comment la mettre à jour tout en conservant les Num uniques et dans
l'ordre

Le 2/ se règle facilement avec des triggers : sur un Insert, tous les
Num des DemiJournee postérieurs à new.DemiJournee sont incrémentées de 1
; sur un Delete, ils sont décrémentés de 1.

Le 1/ se fait en deux étapes (rendons à César : c'est la lecture des
oeuvres de Fred Brouard qui m'a appris ces deux méthodes) :

1a/ créer la liste des demi-journées ouvrées
1b/ numéroter les demi-journées

1a/ c'est relativement facile à faire avec Excel, ou bien avec une
boucle PHP ou SQL dynamique ; c'est également possible en simple SQL
statique, c'est la solution que je te propose ici.

Pour cela, il faut d'abord une table contenant les chiffres de 0 à 9.
C'est une table utilitaire qui te re-servira souvent.

CREATE TABLE Chiffres (Num TINYINT UNSIGNED NOT NULL PRIMARY KEY) ;
INSERT INTO Chiffres (Num)
VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);

Supposons maintenant que ton Calendrier doit partir du 01/01/2006 et
couvrir 1000 jours. Il suffit d'ajouter de 0 à 999 jours à la date de
départ. Cela s'obtient par un produit cartésien (toutes les
combinaisons) entre trois instances de Chiffres, pour les Unités,
Dizaines et Centaines.

CREATE TABLE Calendrier (DemiJournee DateTime UNIQUE) ;

-- création des matinées
INSERT INTO Calendrier (DemiJournee)
SELECT '2006-01-01' + INTERVAL U.Num + 10 * D.Num + 100 * C.Num DAY
FROM Chiffres U
CROSS JOIN Chiffres D
CROSS JOIN Chiffres C
WHERE WEEKDAY(
'2006-01-01' + INTERVAL U.Num + 10 * D.Num + 100 * C.Num DAY
) <> 6 ; -- dimanches exclus

-- création des après-midi
INSERT INTO Calendrier (DemiJournee)
SELECT DemiJournee + INTERVAL 12 HOUR
FROM Calendrier
WHERE WEEKDAY(DemiJournee) NOT IN (2, 5) ; -- mercr et samedis exclus

Il ne te reste plus qu'à éliminer les jours fériés, plus ou moins à la
main selon les cas, par ex. :
-- élimination des 14 juillet
DELETE FROM Calendrier
WHERE DemiJournee LIKE '____-07-14%' ;


1b/

Le numéro d'une demi-journée, c'est le nombre de demi-journées qu'il y a
avant elle. Nous allons donc compter les demi-journées précédent chaque
demi-journée, au moyen d'une jointure d'inégalité :

ALTER TABLE Calendrier ADD Num INT UNSIGNED DEFAULT 0 ;
UPDATE Calendrier C1
INNER JOIN (SELECT C2.DemiJournee, COUNT(*) AS Num
FROM Calendrier C2
INNER JOIN Calendrier C3 ON C2.DemiJournee > C3.DemiJournee
GROUP BY C2.DemiJournee
) AS N ON C1.DemiJournee = N.DemiJournee
SET C1.NUM = N.Num

Cette dernière requête est un peu tordue, en théorie on pourrait se
passer de la sous-requête, mais MySQL n'aime pas qu'on lise sur la table
qu'on est en train de modifier...

Et voilà !
--
Antoun

Guide complet MySQL 5, par Antoine Dinimant, éd. MicroApplication
http://www.microapp.com/livre_mysql_7873.html
helios
2006-10-24 06:04:54 UTC
Permalink
Post by Antoun
Si tu veux tenir compte des jours fériés, il n'y a pas d'autre choix que
de passer par une table calendrier.
Faux
il existe une autre solution qui est le calcul par la requete des jours
feriés mais SQL est trop primitif pour savoir faire
par contre un vrai SGBDR sait faire .

A l'origine Codd avait ecrit SEQUEL pour IBM avec des royalities a PICK pour
le multivalué
SEQUEL donna plein d'autre SGBDR multivalué tel pegasus reality ....... et
SQL qui est un SEQUEL degenerer ou tout ce qui est multivalue est retiré
pour ne pas payer de royalties (d'ailleur Codd ne reconnait pas SQL comme
etant un SGBDR valable) ; les concepts du multivalué sont dans le domaine
public depuis 1993 et des solutions open source en multivalué sont sortie
donc SQL est ringuard puisque ne se justifie plus depuis 1993

l'informatique c'est comme le tennis ; les profs de tennis et ceux qui
ecrivent des livres sur le tennis sont rarement bien classé et encore plus
rarement des champions

Dr Thierry HOLZ
helios services
180 rue de la croix du chene
60250 HEILLES
www.openqm.com02.net
www.pick.com02.net
Fred Brouard - SQLpro
2006-10-23 13:49:20 UTC
Permalink
Post by Jean-Paul Witz
Bonjour
Dans un table, j'ai deux champs: date et duree (en jours).
Je voudrais faire une requête select qui, dans la clause where,
sélectionne les dates+duree inférieure ou égal à aujourd'hui en tenant
Aujourd'hui, nous sommes le dimanche 2006-10-22
si date contient 2006-10-20(c'est un jeudi) et duree contient 1,
l'enregistrement ne doit pas être sélectionné
par contre date contient 2006-10-21(c'est un vendredi) et duree contient
1, l'enregistrement doit être sélectionné, car, jours ouvrés,
vendredi+1=lundi.
Est-il posssible de faire ceci dans une requête Mysql?
Merci
JPW
la seule solution viable est de rajouter à votre modèle un planning tel
que je l'ai décrit dans cet article :
http://sqlpro.developpez.com/cours/gestiontemps/
après vos requêtes vont devenir triviales

A +
--
Frédéric BROUARD, MVP SQL Server, expert bases de données et langage SQL
Le site sur le langage SQL et les SGBDR : http://sqlpro.developpez.com
Audit, conseil, expertise, formation, modélisation, tuning, optimisation
********************* http://www.datasapiens.com ***********************
helios
2006-10-23 16:46:59 UTC
Permalink
Post by Fred Brouard - SQLpro
Post by Jean-Paul Witz
Bonjour
Dans un table, j'ai deux champs: date et duree (en jours).
Je voudrais faire une requête select qui, dans la clause where,
sélectionne les dates+duree inférieure ou égal à aujourd'hui en tenant
Aujourd'hui, nous sommes le dimanche 2006-10-22
si date contient 2006-10-20(c'est un jeudi) et duree contient 1,
l'enregistrement ne doit pas être sélectionné
par contre date contient 2006-10-21(c'est un vendredi) et duree contient
1, l'enregistrement doit être sélectionné, car, jours ouvrés,
vendredi+1=lundi.
Est-il posssible de faire ceci dans une requête Mysql?
Merci
JPW
la seule solution viable est de rajouter à votre modèle un planning tel
http://sqlpro.developpez.com/cours/gestiontemps/
après vos requêtes vont devenir triviales
A +
waff waff waff

l'informatique c'est comme le tennis ; les profs de tennis et ceux qui
ecrivent des livres sur le tennis sont rarement bien classé et encore plus
rarement des champions

Dr Thierry HOLZ
helios services
180 rue de la croix du chene
60250 HEILLES
www.openqm.com02.net
www.pick.com02.net
paul POULAIN
2006-10-24 08:03:47 UTC
Permalink
Post by helios
l'informatique c'est comme le tennis ; les profs de tennis et ceux qui
ecrivent des livres sur le tennis sont rarement bien classé et encore plus
rarement des champions
En tous cas, des champions, on en a au moins un sur ce forum. Et de classe
internationale encore...
Cela dit, tu fais quoi mercredi soir ? J'ai un diner avec des amis et je
voudrais bien t'inviter (si tu acceptes de venir à Marseille même sans S)
--
Paul, désolé mais qui n'a pas pu se retenir...
helios
2006-10-24 08:04:44 UTC
Permalink
Post by paul POULAIN
Post by helios
l'informatique c'est comme le tennis ; les profs de tennis et ceux qui
ecrivent des livres sur le tennis sont rarement bien classé et encore plus
rarement des champions
En tous cas, des champions, on en a au moins un sur ce forum. Et de classe
internationale encore...
Cela dit, tu fais quoi mercredi soir ? J'ai un diner avec des amis et je
voudrais bien t'inviter (si tu acceptes de venir à Marseille même sans S)
--
Paul, désolé mais qui n'a pas pu se retenir...
je ne peux pas venir car j'ai l'intention d'inviter quelque champion du
troll et hors sujet mais je crois que tu pourras te joindre a eux comme
champion :-)

Dr Thierry HOLZ
helios services
180 rue de la croix du chene
60250 HEILLES
www.openqm.com02.net
www.pick.com02.net
helios
2006-10-24 08:05:49 UTC
Permalink
Post by helios
Post by paul POULAIN
Post by helios
l'informatique c'est comme le tennis ; les profs de tennis et ceux qui
ecrivent des livres sur le tennis sont rarement bien classé et encore
plus
Post by paul POULAIN
Post by helios
rarement des champions
En tous cas, des champions, on en a au moins un sur ce forum. Et de classe
internationale encore...
Cela dit, tu fais quoi mercredi soir ? J'ai un diner avec des amis et je
voudrais bien t'inviter (si tu acceptes de venir à Marseille même sans S)
--
Paul, désolé mais qui n'a pas pu se retenir...
je ne peux pas venir car j'ai l'intention d'inviter quelque champion du
troll et hors sujet mais je crois que tu pourras te joindre a eux comme
champion :-)
Dr Thierry HOLZ
helios services
180 rue de la croix du chene
60250 HEILLES
www.openqm.com02.net
www.pick.com02.net
et si on revenait au post d'origine qui etait gerer des durées et des jours
feriés ?

Continuer la lecture sur narkive:
Loading...