Précédent   Forum des professionnels en informatique > Bases de données > Langage SQL
Langage SQL Forum d'entraide sur le langage SQL et sur les questions liées à la conception de schéma (DDL). Cours SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 20/09/2011, 09h35   #1
Membre actif
 
Homme
Développeur informatique
Inscription : mai 2003
Messages : 400
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 30
Localisation : Suisse

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : mai 2003
Messages : 400
Points : 186
Points : 186
Par défaut Date anniversaire et années bissextiles

Hello,

Un petit problème bête: sur un site j'affiche si un utilisateur a son anniversaire, s'il l'a demain ou l'a eu hier.

Ma méthode actuelle :

Je fais ce test dans la requête SQL en utilisant la fonction DAYOFYEAR :

Code :
SELECT DAYOFYEAR(J.DOBJOUEUR) - DAYOFYEAR(CURDATE()) AS QUAND
Ceci me retourne une valeur en sachant que je ne garde que les valeurs entre -1 et 1 signifiant si l'anniversaire a eu lieu la veille, a lieu aujourd'hui ou aura lieu demain.


Le problème : ça ne fonctionne plus correctement si un utilisateur est né lors d'une année bissextile ou si on se trouve dans une année bissextile.

Avez-vous des idées pour faire ce test en PHP ?
MiJack est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 09h51   #2
Modérateur
 
Inscription : septembre 2010
Messages : 7 131
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 131
Points : 8 491
Points : 8 491
il l'a eu n'y hier ni demain puisque le jour n'existe pas, t’embêtes pas pour ce genre de chose
__________________
http://blog.stealth35.com/
stealth35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 10h37   #3
Membre actif
 
Homme
Développeur informatique
Inscription : mai 2003
Messages : 400
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 30
Localisation : Suisse

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : mai 2003
Messages : 400
Points : 186
Points : 186
Si un utilisateur est né le 10 juin, ce jour existe que l'année soit bissextile ou non. Par contre le calcul DAYOFYEAR ne retourne pas la même valeur, ce qui cause mon problème.

Pour le cas extrême où un utilisateur serait né le 29 février, je peux gérer par un If.
MiJack est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 10h49   #4
Modérateur
 
Inscription : septembre 2010
Messages : 7 131
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 131
Points : 8 491
Points : 8 491
fait ton if alors ou est le problème ?
__________________
http://blog.stealth35.com/
stealth35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 10h58   #5
Membre actif
 
Homme
Développeur informatique
Inscription : mai 2003
Messages : 400
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 30
Localisation : Suisse

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : mai 2003
Messages : 400
Points : 186
Points : 186
Citation:
Envoyé par stealth35 Voir le message
fait ton if alors ou est le problème ?
Le but est d'avoir une fonction qui retourne de -1 à 1 pour savoir si un jour se situe avant ou après le jour courant de manière simple. ça éviterait de devoir tout tester "1. L'utilisateur est-il né une année bissextile, 2. Sommes-nous dans une année bissextile, 3. L'utilisateur est-il né un 29 février" et de gérer tous ces cas y compris lorsqu'ils s'imbriquent.
N'y a-t-il pas de fonction PHP de comparaison de date permettant de gérer ces cas ?
MiJack est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 11h16   #6
Modérateur
 
Inscription : septembre 2010
Messages : 7 131
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 131
Points : 8 491
Points : 8 491
il va bien falloir lui définir une date par contre, si on est pas dans un année bissextile son anniversaire c'est le 28 ou 1 ? sinon tu verras que ça colle pas
__________________
http://blog.stealth35.com/
stealth35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 11h27   #7
Membre actif
 
Homme
Développeur informatique
Inscription : mai 2003
Messages : 400
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 30
Localisation : Suisse

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : mai 2003
Messages : 400
Points : 186
Points : 186
La date c'est la date de naissance de l'utilisateur, je reprends mon exemple du 10 juin. Ma fonction actuelle dans la requête SQL DAYOFYEAR() ne retourne pas la même valeur si l'utilisateur est né le 10 juin 1996 (bissextile) ou 10 juin 1997.

Effectivement comme tu le dis le problème se pose uniquement si l'utilisateur est né une année bissextile après le 29 février, ce qui complique encore l'affaire.

Bref, je cherche un moyen d'afficher "John Doe a son anniversaire hier / aujourd'hui / demain" en gérant tous ces cas. Je pensais qu'il existait des moyens simples en PHP, mais si ce n'est pas le cas je gérerai dans une fonction plus complexe.
MiJack est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 13h25   #8
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 11 029
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur d'études en informatique
Secteur : Enseignement

Informations forums :
Inscription : août 2006
Messages : 11 029
Points : 18 328
Points : 18 328
Envoyer un message via MSN à CinePhil
Facile à faire en SQL avec les fonctions de dates propre à ton SGBD et un CASE WHEN.
Avec MySQL, ça donnerait ceci :
Code :
1
2
3
4
5
6
SELECT 
    CASE
        WHEN DATEDIFF(DOBJOUEUR, CURRENT_DATE) = 1 THEN 'demain'
        WHEN DATEDIFF(DOBJOUEUR, CURRENT_DATE) = (-1) THEN 'hier'
        ELSE 'un autre jour'
    END AS Quand
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
À la maison comme au bureau, j'utilise Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française !
Linuxiens, comptez-vous !
CinePhil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 13h34   #9
Modérateur
 
Avatar de al1_24
 
Homme Alain
Ingénieur d'études décisionnel
Inscription : mai 2002
Messages : 4 446
Détails du profil
Informations personnelles :
Nom : Homme Alain
Âge : 51
Localisation : France, Val de Marne (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études décisionnel
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 4 446
Points : 7 545
Points : 7 545
Nous sommes ici sur le forum Langage SQL, je n'utiliserai donc que les fonctions normalisées pour résoudre ton problème.

L'expression la plus simple pour calculer une date d'anniversaire est la suivante :
Code :
dobjoueur + INTERVAL (EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM dobjoueur)) YEAR
Donc pour calculer ton hier-aujourd’hui-demain, il suffirait de se baser sur le résultat de CURRENT_DATE - (dobjoueur + INTERVAL (EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM dobjoueur)) YEAR).

Malheureusement, lorsqu'on arrive sur le début/fin d'année, le résultat n'est plus cohérent.

Je suis donc arrivé à la requête suivante :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SELECT  anniv + INTERVAL (CASE WHEN reste1 <= 1 THEN 0 WHEN reste2 <= 1 THEN -1 WHEN reste3 <= 1 THEN 1 END) YEAR   AS anniversaire
    ,   CASE CURRENT_DATE - (anniv + INTERVAL (CASE WHEN reste1 <= 1 THEN 0 WHEN reste2 <= 1 THEN -1 WHEN reste3 <= 1 THEN 1 END) YEAR)
            WHEN +1 THEN 'hier'
            WHEN  0 THEN 'aujourd''hui'
            WHEN -1 THEN 'demain'
        END AS quand
FROM    (   SELECT  dobjoueur + INTERVAL (EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM dobjoueur)) YEAR  AS anniv
                ,   ABS(CURRENT_DATE - (dobjoueur + INTERVAL (EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM dobjoueur)) YEAR))    AS reste1
                ,   ABS(CURRENT_DATE - (dobjoueur + INTERVAL (EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM dobjoueur) - 1) YEAR)) AS reste2
                ,   ABS(CURRENT_DATE - (dobjoueur + INTERVAL (EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM dobjoueur) + 1) YEAR)) AS reste3
            FROM    matable
        )   AS  tmp
WHERE   reste1 <= 1
    OR  reste2 <= 1
    OR  reste3 <= 1
Je ne conserve pas dans les résultats les personnes dont l'anniversaire est plus lointain qu'un jour.

PS: A vérifier car je n'ai testé que sur le papier !
__________________
Modérateur Langage SQL
Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
N'oubliez pas le bouton et pensez aux balises [code]
Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
al1_24 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 03h29.


 
 
 
 
Partenaires

Hébergement Web