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 :

Question à propos de la clause GROUP BY [11g]


Sujet :

SQL Oracle

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2013
    Messages : 11
    Points : 12
    Points
    12
    Par défaut Question à propos de la clause GROUP BY
    Bonjour,

    Je ne comprends pas pourquoi il est obligatoire d'ajouter dans la clause GROUP BY toutes les colonnes du SELECT lorsque la clé primaire suffirait.

    Exemple: J'ai une table Clients et une table Ordres (synonyme de transaction dans ce cas). Je désire obtenir la somme des ordres de chaque client ainsi que son prénom.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT Cli.Prenom, SUM(Ord.Montant) FROM Clients Cli
    INNER JOIN Ordres Ord
    ON Cli.Num_cli = Ord.Num_cli
    GROUP BY Cli.Prenom;
    Cependant le résultat de cette requête est faux. Si j'ai deux clients prénommé Albert, le résultat de cette requête groupera les lignes des clients ayant le même prénom. Jusqu'ici je comprends, c'est assez normal.

    Pour rendre cette requête correcte, il faudrait grouper aussi par la clé primaire comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT Cli.Prenom, SUM(Ord.Montant) FROM Clients Cli
    INNER JOIN Ordres Ord
    ON Cli.Num_cli = Ord.Num_cli
    GROUP BY Cli.Prenom, Cli.Num_cli;
    Mais pourquoi on ne pourrait pas écrire cette requête de cette façon:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT Cli.Prenom, SUM(Ord.Montant) FROM Clients Cli
    INNER JOIN Ordres Ord
    ON Cli.Num_cli = Ord.Num_cli
    GROUP BY Cli.Num_cli;
    En effet je trouve que de cette façon ça devrait fonctionner. Mais je reçois bien une erreur ORA-00979: n'est pas une expression GROUP BY.

    D'avance merci beaucoup et meilleures salutations.

  2. #2
    Expert éminent sénior 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
    Points : 11 252
    Points
    11 252
    Par défaut
    Citation Envoyé par cappuccino77 Voir le message
    Mais pourquoi on ne pourrait pas écrire cette requête de cette façon:

    SELECT Cli.Prenom, SUM(Ord.Montant) FROM Clients Cli
    INNER JOIN Ordres Ord
    ON Cli.Num_cli = Ord.Num_cli
    GROUP BY Cli.Num_cli;
    ...
    Votre proposition corresponde en fait à cette requête:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Select Cli1.Prenom,
           grp.Tot_Mnt
      From Clients Cli1
           Join
           (Select Cli.Num_cli, 
                   Sum(Ord.Montant) Tot_Mnt
              From Clients Cli
                   Join 
                   Ordres Ord
                On Cli.Num_cli = Ord.Num_cli
             Group By Cli.Num_cli
           ) grp 
        On  Cli1.Num_cli = grp.Num_cli

  3. #3
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par cappuccino77 Voir le message
    En effet je trouve que de cette façon ça devrait fonctionner
    Ça devrait en effet, selon la norme SQL, puisque Prenom est en dépendance fonctionnelle de Num_cli

    C'est au niveau de l'implémentation de celle-ci que les SGBD prennent souvent leurs aises.

    La plupart sont plus restrictifs et exigent que toutes les colonnes soient inclues dans le group by dès lors qu'elles ne font pas partie d'une fonction d'agrégat.

    MySQL lui, autorise tout (et n'importe quoi !). Mais attention aux résultats... (Mysql renvoi la première valeur qu'il trouve).

  4. #4
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2013
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    @mnitu, merci mais je cherchais plus à comprendre pourquoi ça ne fonctionnait pas plutôt qu'une alternative plus compliqué (et plus coûteuse au niveau de l'exécution).

    @aieeeuuuuu, merci beaucoup pour votre réponse. Peut-être que cette restriction sert à s'assurer que le résultat soit correct (et préférer retourner une erreur plutôt qu'un résultat faussé) et permet aussi une implémentation plus facile. Bien entendu ce ne sont que des suppositions de ma part qui valent ce qu'elles valent... Qu'en pensez-vous?

  5. #5
    Expert éminent sénior 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
    Points : 11 252
    Points
    11 252
    Par défaut
    Citation Envoyé par cappuccino77 Voir le message
    @mnitu, merci mais je cherchais plus à comprendre pourquoi ça ne fonctionnait pas plutôt qu'une alternative plus compliqué (et plus coûteuse au niveau de l'exécution).
    ...
    Coûteuse ou pas c'est ce que vous demandez en fait. Parce que sinon j'avais trouvé que vos remarques concernant le résultat incorrect, vous mène sur la bonne piste. Pour moi l'idée d'une requête donnant un résultat incorrect à la place d'une erreur c'est tout simplement un bug!

  6. #6
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par cappuccino77 Voir le message
    Peut-être que cette restriction sert à s'assurer que le résultat soit correct (et préférer retourner une erreur plutôt qu'un résultat faussé) et permet aussi une implémentation plus facile. Bien entendu ce ne sont que des suppositions de ma part qui valent ce qu'elles valent... Qu'en pensez-vous?
    Il me semble qu'avant, la norme SQL elle même n'incluait pas non plus cette subtilité concernant les dépendances fonctionnelles, et exigeait également dans le GROUP BY l'ensemble des colonnes présentes dans le SELECT sans fonction d'agrégat.
    Quand cette subtilité est arrivée (dans la norme de 1999 je crois, sans aucune certitude), les SGBD avaient déjà, et depuis longtemps implémenté le GROUP BY (heurseuement !).
    Du coup, implémenter maintenant cela n'est certainement pas une priorité, sachant que ça n'améliorera pas les performances, mais simplement le confort pour l'écriture des requêtes. Mais là aussi, ce ne sont que des suppositions...

    Mais ce n'est au final qu'une question d'habitude. Pour simplifier la chose, il suffit de regrouper en fin de SELECT les colonnes avec fonction d'agrégat, et de construire le GROUP BY par un copier/coller du début du SELECT. Bien sûr, dans certaines requêtes plus complexes, cela n'est pas toujours aussi simple...

  7. #7
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2013
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    Merci beaucoup c'est très clair.

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

Discussions similaires

  1. Question à propos des compilateurs
    Par elf dans le forum Autres éditeurs
    Réponses: 4
    Dernier message: 20/07/2005, 18h00
  2. Question à propos des niveaux de transaction
    Par davy.g dans le forum Oracle
    Réponses: 3
    Dernier message: 18/01/2005, 16h31
  3. Petite question à propos du redbook...
    Par Michaël dans le forum OpenGL
    Réponses: 3
    Dernier message: 04/11/2004, 13h54
  4. Petite question à propos d'une requete
    Par ViBy dans le forum Langage SQL
    Réponses: 4
    Dernier message: 15/09/2004, 13h21
  5. Une question à propos des thread
    Par tscoops dans le forum C++Builder
    Réponses: 4
    Dernier message: 07/11/2003, 15h03

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