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 :

Group by avec la fonction Max()


Sujet :

SQL Oracle

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    254
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 254
    Par défaut Group by avec la fonction Max()
    Bonjour à tous,

    Je voudrais récupérer une (et une seule) ligne dans ma table en filtrant sur le champs date le plus récent.

    Structure de ma table, qu'on va appeler TABLE_TEST

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    |DATE   |VALEUR1  |VALEUR2   |
    |200501   | TOTO    | TRUC     |
    |200605   | TOTO    | TRUC     |
    |200702   | TOTO    | MACHIN   |
    |200602   | TITI    | MACHIN   |
    |200701   | TATA    | CHOSE    |
    et je lance cette requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    select MAX(to_number(A.DATE)), A.VALEUR1, A.VALEUR2
    from TABLE_TEST A
    group by A.DATE, A.VALEUR1, A.VALEUR2
    mais ça me renvoie ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    |DATE   |VALEUR1  |VALEUR2   |
    |200605   | TOTO    | TRUC     |
    |200702   | TOTO    | MACHIN   |
    |200602   | TITI    | MACHIN   |
    |200701   | TATA    | CHOSE    |
    ce qui est normal, je l'admets, puisque je groupe par VALEUR1 et VALEUR2
    mais moi ce que je voudrais c'est arriver à ce résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    |DATE   |VALEUR1  |VALEUR2   |
    |200702   | TOTO    | MACHIN   |
    mais quand j'enlève les deux champs dans le group by, il me fait une erreur...


    Merci de votre aide! ^^

    NB : l'intitulé du champs date est trompeur, en fait ce sont des varchar2(6)

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2005
    Messages
    316
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 316
    Par défaut
    si ce que tu veux c'est avoir valeur 1 et 2 pour la date max
    alors :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     
    SELECT A.DATE, A.VALEUR1, A.VALEUR2
    FROM TABLE_TEST A
    where a.date=(select MAX(b.DATE) from table_test b)

  3. #3
    Membre éclairé
    Inscrit en
    Novembre 2002
    Messages
    549
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 549
    Par défaut
    Citation Envoyé par c.langlet Voir le message
    si ce que tu veux c'est avoir valeur 1 et 2 pour la date max
    alors :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     
    SELECT A.DATE, A.VALEUR1, A.VALEUR2
    FROM TABLE_TEST A
    where a.date=(select MAX(b.DATE) from table_test b)
    pour une question de tuning il faut éviter les requetes imbriquées
    la solution passe par un bloc WITH que tu mets avant.

    je t'invite à faire une recherche sur le forum pour trouver des posts sur ce sujet

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 31
    Par défaut
    Citation Envoyé par PpPool Voir le message
    pour une question de tuning il faut éviter les requetes imbriquées
    la solution passe par un bloc WITH que tu mets avant.

    je t'invite à faire une recherche sur le forum pour trouver des posts sur ce sujet
    Bonjour,

    Ta réponse concernant les blocs WITH m'intéresse. J'ai cherché sur le forum mais je n'ai pas trouvé. Pour moi, la solution est d'utiliser un bloc "not exists" à la place de la requête imbriquée, par contre je n'ai jamais entendu parlé de ces blocs With. Si tu pouvais me guider sur une piste merci !
    Avec le not exists :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT A.DATE, A.VALEUR1, A.VALEUR2
    FROM TABLE_TEST A
    WHERE not exists (select 1
                      from table_test b
                      where b.date > a.date )

  5. #5
    Membre éprouvé
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Mai 2007
    Messages
    126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2007
    Messages : 126
    Par défaut
    essayes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    SELECT A.DATE, A.VALEUR1, A.VALEUR2
    FROM TABLE_TEST A,
      (select MAX(A.DATE) date FROM TABLE_TEST) T
    where A.date = T.date
    Ca devrait etre aussi efficace que with, comme on n'utilise qu'une fois la valeur retournée

  6. #6
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Le WITH permet d'aliaser une sous-requête avant la requête proprement dite.
    Par contre je n'ai pas trouvé plus d'éclaircissement quant à l'optimisation apporté par cette syntaxe (exécution unique ?).

    En tout cas voici pour la syntaxe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    WITH SR AS (SELECT MAX(DATE) date_max FROM TABLE_TEST)
    SELECT * FROM TABLE_TEST
    WHERE date = SR.date_max

  7. #7
    Membre éclairé
    Inscrit en
    Novembre 2002
    Messages
    549
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 549
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Le WITH permet d'aliaser une sous-requête avant la requête proprement dite.
    Par contre je n'ai pas trouvé plus d'éclaircissement quant à l'optimisation apporté par cette syntaxe (exécution unique ?).

    En tout cas voici pour la syntaxe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    WITH SR AS (SELECT MAX(DATE) date_max FROM TABLE_TEST)
    SELECT * FROM TABLE_TEST
    WHERE date = SR.date_max
    Attention, il faut ajouter ta table SR, ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    WITH SR 
    AS (
          SELECT MAX(DATE) AS date_max 
          FROM TABLE_TEST)
    SELECT * 
    FROM TABLE_TEST, SR
    WHERE date = SR.date_max
    voilà qui est mieux
    le bloc WITH est une parade très performante pour éviter les requetes imbriquées, il n'est exécuté qu'une seule fois
    après c'est comme tout, il faut comparer les explain plan
    je ne me suis pas plus attardé que çà sur ta requete, mais il me semble aussi que tu devrais regarder les fonctions analytiques, tu as un tuto excellent sur DVP

  8. #8
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Merci pour la correction (nécessaire) et les précisions.

  9. #9
    Membre Expert Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Par défaut
    Salut !

    Je suis pas sûr de ça PpPool...
    A priori, il se peut que la requête de Waldar fasse la même chose.
    Ce qu'il peut se passer, c'est que le CBO choissise de merger la vue (c'est à dire la sous requête d'agrégat) dans la requête principale, ce qui pourrirait les perfs.

    Mais si tu ajoutes le hint : /*+ no_merge(TonAlias) */, tu obtiens le même résultat, soit une VIEW sur le SORT GROUP BY. (la sous-requête n'est pas mergée dans la requête principale)

    Quand tu utilises le WITH, tu peux utiliser le hint /*+materialize */ pour être sûr que la vue (définie dans le with) soit matérialisée par Oracle.
    (faites le test, et regardez l'explain plan, c'est rigolo).

    Voilà voilà...

  10. #10
    Membre chevronné Avatar de xdescamp
    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 300
    Par défaut
    Hello,

    L'utilisation d'une fonction analytique permet d'obtenir le résultat que tu veux de façon optimisée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT MAX(TO_NUMBER(a.date)),
           MIN (a.valeur1) KEEP (DENSE_RANK FIRST ORDER BY TO_NUMBER(a.date) DESC),
           MIN (a.valeur2) KEEP (DENSE_RANK FIRST ORDER BY TO_NUMBER(a.date) DESC)
    FROM table_test a;
    Si tu regardes l'explain plan, la table n'est accédée qu'une seule fois.

  11. #11
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    Citation Envoyé par xdescamp Voir le message
    Hello,

    L'utilisation d'une fonction analytique permet d'obtenir le résultat que tu veux de façon optimisée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT MAX(TO_NUMBER(a.date)),
           MIN (a.valeur1) KEEP (DENSE_RANK FIRST ORDER BY TO_NUMBER(a.date) DESC),
           MIN (a.valeur2) KEEP (DENSE_RANK FIRST ORDER BY TO_NUMBER(a.date) DESC)
    FROM table_test a;
    Si tu regardes l'explain plan, la table n'est accédée qu'une seule fois.
    Ce n'est pas une fonction analytique dans ton exemple.
    Voilà la diagramme de syntaxe pour la version analytique
    DENSE_RANK( ) OVER([query_partition_clause] order_by_clause)

  12. #12
    Membre chevronné Avatar de xdescamp
    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 300
    Par défaut
    OK, au temps pour moi.

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 24/01/2009, 17h04
  2. faire un GROUP BY avec la fonction MAX()
    Par crazymad dans le forum Développement
    Réponses: 4
    Dernier message: 01/12/2008, 16h40
  3. requete SQl avec la fonction max () qui ne marche pas
    Par eclipse012 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 09/11/2006, 15h32
  4. [Débutant / SQL] Requête avec la fonction MAX
    Par bugmenot dans le forum Access
    Réponses: 3
    Dernier message: 14/04/2006, 11h43
  5. Pb avec la fonction Max d'access
    Par abaad dans le forum Access
    Réponses: 1
    Dernier message: 03/04/2006, 18h43

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