IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Oracle Discussion :

Calcul de l'age exact dans une requete


Sujet :

SQL Oracle

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 64
    Points : 54
    Points
    54
    Par défaut Calcul de l'age exact dans une requete
    Bonjour
    Je souhaite extraire l'age arrondi par defaut d'une personne en fonction de la date du jour et de sa date de naissance, voici ma requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    select trunc((SYSDATE - date_naissance) / (365))
    from personne where nom = 'DUPONT'
    La différence entre 2 dates donnant le nbre de jours donc je divise par 365 .

    Existe t'il une fonction plus précise car ce n'est pas tout à fait juste dans la mesure où il y a des années de 366 jours.
    Merci

  2. #2
    Membre éprouvé Avatar de laurentibus
    Inscrit en
    Mars 2008
    Messages
    875
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Mars 2008
    Messages : 875
    Points : 908
    Points
    908
    Par défaut
    peut etre avec months_between
    Nombre de mois entre date1 et date2. La partie décimale est obtenue en divisant le nombre de jours par 31.
    MONTHS_BETWEEN('26-JUN-90','25-DEC-93')=40,967742 MONTHS_BETWEEN('26-JUN-90','26-DEC-89')=-6
    il ne te reste plus qu a divisé par 12 .... et toutes les années ont 12 mois
    ... un flash ... et ça repart

    700R ... catch me if u can

    Best regards,
    .

  3. #3
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Oui la fonction MONTHS_BETWEEN vous donnera un résultat juste même pour les années bissextiles.

    Depuis je ne sais pas quelle version, on retrouve le type de donnée INTERVAL qui est là pour couvrir pour ce genre de cas (même si je le trouve encore trop rigide au niveau des syntaxes, précisions et opérations).

    Regardez cette requête qui reprend ces divers éléments :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    select
        id,    
        dt_naiss,
        floor(months_between(trunc(sysdate), dt_naiss)/12) as age_mb,
        (trunc(sysdate) - dt_naiss) YEAR(4) to MONTH as int_ym,
        extract(year from (trunc(sysdate) - dt_naiss) YEAR(4) to MONTH) as age_int
    from
    (
        select 1 id, to_date('01/01/2009', 'dd/mm/yyyy') dt_naiss from dual union all
        select 2, to_date('08/05/1945', 'dd/mm/yyyy') from dual union all
        select 3, to_date('11/11/1918', 'dd/mm/yyyy') from dual union all
        select 4, to_date('02/12/1805', 'dd/mm/yyyy') from dual union all
        select 5, to_date('14/07/1789', 'dd/mm/yyyy') from dual union all
        select 6, to_date('11/11/1111', 'dd/mm/yyyy') from dual union all
        select 7, to_date('01/01/0001', 'dd/mm/yyyy') from dual
    )
    order by id asc

  4. #4
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Oui la fonction MONTHS_BETWEEN vous donnera un résultat juste même pour les années bissextiles.
    c'est faux...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT
        floor(months_between(date '2010-02-28', date '1992-02-29')/12) AS age_mb
    from dual;
    18
    si tu es né un 29 février 1992, tu devras attendre le 1er mars 2010 pour atteindre tes 18 ans

    c'est pourquoi je préfère une version maison...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT
        trunc(to_char(date '2010-02-28','YYYY.MMDD')-to_char(date '1992-02-29','YYYY.MMDD')) AS age_mb
    from dual; 
    17

  5. #5
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Oui mais est-ce plus juste ou est-ce plus faux pour un bissexte de fêter son anniversaire le 28/02 ou le 01/03 ?

    Une rapide recherche ne fournit pas de réponse formelle, le jour de l'anniversaire étant apparement laissé au choix de l'intéressé.

    Donc je ne considère par votre soustraction, certes astucieuse, comme étant plus juste que months_between, mais c'est intéressant d'avoir une munition supplémentaire

    Celà dit ça m'a permi de voir quelque chose de troublant avec l'intervalle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    select
        A,
        (A - B) YEAR to MONTH itv,
        trunc(months_between(A, B)/12) age_mb,
        extract(year from (A - B) YEAR to MONTH) as age_int,
        trunc(to_char(A,'YYYY,MMDD') - to_char(B,'YYYY,MMDD')) age_ls -- ',' est le symbole décimal sur ma base de test
    from
    (
        select to_date('01/03/2010', 'dd/mm/yyyy') A, to_date('29/02/1992', 'dd/mm/yyyy') B from dual union all
        select to_date('28/02/2010', 'dd/mm/yyyy') A, to_date('29/02/1992', 'dd/mm/yyyy') B from dual union all
        select to_date('14/02/2010', 'dd/mm/yyyy') A, to_date('29/02/1992', 'dd/mm/yyyy') B from dual union all
        select to_date('13/02/2010', 'dd/mm/yyyy') A, to_date('29/02/1992', 'dd/mm/yyyy') B from dual
    )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    DATE_A		ITV	AGE_MB	AGE_INT	AGE_LS
    01/03/2010	+18-00	18	18	18
    28/02/2010	+18-00	18	18	17
    14/02/2010	+18-00	17	18	17
    13/02/2010	+17-11	17	17	17
    Il semblerait que l'intervalle s'arrondisse, 11.5 mois devenant 12 mois qui devient donc +1 an.

    Donc en fait il ne faut surtout pas l'utiliser pour calculer un âge !

  6. #6
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    Waldar,
    C'est vrai que celui qui est né le 29 février fête son anniversaire quand il veut.

    Par contre si tu commets un crime le 28 février de tes 18 ans, les conséquences juridiques de ton âge auront une grande différence.

    Pour être sûr il faudrait fouiller les textes de loi.

    Bon, j'ai trouvé ça :

    http://www.mayenne.pref.gouv.fr/pdf/...list69_352.pdf
    lorsqu’il s’agit d’une personne née le 29 février, il conviendra
    d’admettre qu’elle aura atteint sa majorité le 28 février de l’année de son dix-huitième anniversaire
    Un point pour toi

  7. #7
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Je n'ai rien fait, c'est Oracle qui a codé months_between

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 64
    Points : 54
    Points
    54
    Par défaut
    Bonjour

    En tout j'ai mainteanant un pb quand je fais ma requête avec hibernante : le "/" de /12 , il me jette
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select MONTHS_BETWEEN (SYSDATE , a.dateNaissance)/(12) , code,a.sexe, count(*) from Personne a where  ...........
    group by MONTHS_BETWEEN (SYSDATE , a.dateNaissance)/(12), a.sexe 
    order by MONTHS_BETWEEN (SYSDATE , a.dateNaissance)/(12),a.sexe
    Alors que le calcul marche bien sans le / 12 , et je n'ai pas encore esssayé le TRUNC.
    Je vais poster aussi ce message dans le forum hibernate car là c'est plutôt un pb hibernate

  9. #9
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    Citation Envoyé par sandrine49 Voir le message
    Bonjour

    En tout j'ai mainteanant un pb quand je fais ma requête avec hibernante : le "/" de /12 , il me jette
    Quel est le message d'erreur?

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 64
    Points : 54
    Points
    54
    Par défaut
    Bonjour
    J'ai ce messagae d'erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *** ERROR: <AST>:0:0: unexpected AST node: /

  11. #11
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    et ceci?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SELECT 
      TRUNC(MONTHS_BETWEEN (SYSDATE , a.dateNaissance)/12) , 
      code,a.sexe, count(*) 
    FROM Personne a 
    WHERE  ...........
    GROUP BY 
      TRUNC(MONTHS_BETWEEN (SYSDATE , a.dateNaissance)/12) , 
      a.sexe 
    ORDER BY 
      TRUNC(MONTHS_BETWEEN (SYSDATE , a.dateNaissance)/12) , 
      a.sexe

  12. #12
    Rédacteur
    Avatar de Bruno2r
    Homme Profil pro
    Exploitation des données
    Inscrit en
    Décembre 2006
    Messages
    2 566
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Exploitation des données
    Secteur : Santé

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 566
    Points : 4 780
    Points
    4 780
    Par défaut
    Bonsoir,
    Voici comment je procède pour calculer l'âge :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT A.DATENAISS, sysdate, 
    extract(year from sysdate)-extract(year from A.DATENAISS) + 
    decode(sign(extract(month from sysdate) - 
    extract(month from A.DATENAISS)),-1,-1,0,0,1,0) as AGE
    FROM T_PERSONNE A
    On peut aussi remplacer la date système par la date d'un événement par exemple dans les calculs suivants le début d'un séjour :
    ni NAISSDATE SEJDATE AGE
    01 02/03/1991 17/07/2008 17
    02 17/01/1992 07/10/2008 16
    03 06/12/1990 07/07/2008 17
    04 05/11/1992 06/08/2008 15
    05 03/12/1991 09/07/2008 16
    06 29/10/1991 20/10/2008 17
    07 27/06/1993 28/07/2008 15
    08 10/08/1993 08/07/2008 14
    09 26/08/1993 21/07/2008 14
    10 23/01/1993 27/10/2008 15
    11 14/02/2000 07/01/2009 8
    12 02/09/1999 14/11/2008 9
    13 24/04/1992 03/11/2008 16
    Précisez la VERSION !
    Un message vous a aidé ? Votez en cliquant sur Pensez au bouton
    Tutoriels BO et FAQ BO
    "A vouloir repousser ses limites ... On risque d'en prendre connaissance !!!"

  13. #13
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    bon, c'est comme dire que tout le monde a son anniversaire le 1er du mois

  14. #14
    Rédacteur
    Avatar de Bruno2r
    Homme Profil pro
    Exploitation des données
    Inscrit en
    Décembre 2006
    Messages
    2 566
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Exploitation des données
    Secteur : Santé

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 566
    Points : 4 780
    Points
    4 780
    Par défaut
    Citation Envoyé par laurentschneider Voir le message
    bon, c'est comme dire que tout le monde a son anniversaire le 1er du mois
    Bien sûr mais moi ça correspondait à mon besoin (en termes de précision).
    Rien n'empèche de faire la même chose sur le Numéro de jour dans l'Année
    Précisez la VERSION !
    Un message vous a aidé ? Votez en cliquant sur Pensez au bouton
    Tutoriels BO et FAQ BO
    "A vouloir repousser ses limites ... On risque d'en prendre connaissance !!!"

  15. #15
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    Citation Envoyé par Bruno2r Voir le message
    Rien n'empèche de faire la même chose sur le Numéro de jour dans l'Année
    Bof... ca ne va pas jouer car le 60e jour n'est pas toujours en mars...

  16. #16
    Rédacteur
    Avatar de Bruno2r
    Homme Profil pro
    Exploitation des données
    Inscrit en
    Décembre 2006
    Messages
    2 566
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Exploitation des données
    Secteur : Santé

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 566
    Points : 4 780
    Points
    4 780
    Par défaut
    Citation Envoyé par Bruno2r Voir le message
    Bien sûr mais moi ça correspondait à mon besoin (en termes de précision).
    Rien n'empèche de faire la même chose sur le Numéro de jour dans l'Année
    Citation Envoyé par laurentschneider Voir le message
    Bof... ca ne va pas jouer car le 60e jour n'est pas toujours en mars...
    Tu as absolument raison ! J'ai fait un peu vite sur ce coup là ...
    En fait dans ma réponse d'hier j'avais envisagé d'imbriquer dans le décode sur le signe de l'écart sur mois le test du jour dans le mois (quite à gérer pour février la notion de dernier jour du mois)....
    ça alourdit c'est sûr mais tout est envisageable selon le besoin de précision.
    Pour ma part, j'opterais pour une Fonction en PL/SQL ce qui assurerait une lisibilité totale du SELECT l'utilisant.
    Précisez la VERSION !
    Un message vous a aidé ? Votez en cliquant sur Pensez au bouton
    Tutoriels BO et FAQ BO
    "A vouloir repousser ses limites ... On risque d'en prendre connaissance !!!"

  17. #17
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    moi j'aime bien mon trunc(to_char(d2,'YYYY.MMDD')-to_char(d1,'YYYY.MMDD'))


  18. #18
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2005
    Messages : 55
    Points : 61
    Points
    61
    Par défaut
    Voici une fonction assez correcte a mon sens, du moin, jamais de problème avec.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
       IF to_number(to_char(p_date,'mm')||to_char(p_date,'dd')) >= 
       	  to_number(to_char(p_birth_date,'mm')||to_char(p_birth_date,'dd'))
       THEN
          v_return :=  to_number(to_char(p_date,'yyyy')) - to_number(to_char(p_birth_date,'yyyy'));
       ELSE
       	  v_return :=  to_number(to_char(p_date,'yyyy')) - to_number(to_char(p_birth_date,'yyyy')) - 1;
       END IF;

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. calcul différence entre deux heures dans une requete
    Par cornet04 dans le forum Requêtes et SQL.
    Réponses: 6
    Dernier message: 18/03/2015, 16h37
  2. calcul pourcentage dans une requete imbriquée
    Par timal78 dans le forum Langage SQL
    Réponses: 1
    Dernier message: 10/07/2007, 14h28
  3. Problèmes de calcul dans une requete imbriquée
    Par LeNovice dans le forum Langage SQL
    Réponses: 6
    Dernier message: 21/03/2007, 16h56
  4. colonne de calcul dans une requête
    Par Virgile59 dans le forum Access
    Réponses: 2
    Dernier message: 27/10/2006, 14h55
  5. Calculs dans une requete avec conditions multiples
    Par Sha1966 dans le forum Access
    Réponses: 3
    Dernier message: 13/01/2006, 15h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo