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

Langage SQL Discussion :

Clause DISTINCT [Débutant(e)]


Sujet :

Langage SQL

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 4
    Points : 4
    Points
    4
    Par défaut Clause DISTINCT
    Bonjour,

    Je voudrais comprendre la différence :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT DISTINCT refcommande, count(refproduit)As Qté
    FROM CommandeProduits
    GROUP BY refcommande, Qté;
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT refcommande, count(refproduit)As Qté
    FROM
    (SELECT DISTINCT refcommande
    FROM CommandeProduits)
    GROUP BY refcommande, Qté;
    Pourquoi certaine fois, DISTINCT doit se mettre dans un second SELECT comme le second exemple ?

    La requête est : pour chaque commande, la quantité totale des produits commandés.

    Merci de votre aide.

  2. #2
    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
    Bonjour,

    A première vue, je dirait que la différence entre le résultat de ces deux requêtes sera... le message d'erreur !

    Aucune des deux requêtes n'est correcte.

    Si vous postiez les vrais requêtes, on pourrait mieux vous aider, mais je pense que le but de la deuxième est de compter le nombre de produits distinct dans chaque commande. Dans ce cas vous pouvez faire simplement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    COUNT(DISTINCT refproduit)
    dans la première requête (après avoir corrigé le GROUP BY de celle-ci bien sur, et supprimé le premier DISTINCT qui ne sert à rien...)

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 4
    Points : 4
    Points
    4
    Par défaut Suite
    J'ai certainement du faire une erreur, mais voici un autre exemple qui est correcte (corrigé de mon TD) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT nom, count (refintervention) As Nb
    FROM 
    (SELECT DISTINCT matricule, nom, refintervention
    FROM (membre INNER JOIN déplacement ON membre.matricule = déplacement.refmatricule)
    INNER JOIN intervention 
    ON intervention.idintervention = déplacement. refintervetion )
    GROUP BY nom, matricule ;
    A vrai dire, je ne cherche pas réellement à savoir l'exactitude mes requêtes, je cherche à comprendre pourquoi certaine fois les DISTINCT sont placés à cet endroit de la requête.

    Autre question (j'ai un partiel demain), j'ai remarqué certaines fois, qu'on écrivait nomtable.champ après le SELECT et certaine fois uniquement le champ. Faut-il mettre nomtable.champ à partir du moment où il y a une jointure ?

    Merci de votre aide.

  4. #4
    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
    Je ne vois pas d'autre raison que ne pas compter plusieurs fois la même intervention. Surtout qu'en l’occurrence, il peut y avoir plusieurs déplacements par intervention je suppose...

    Mais là encore il me semble qu'une COUNT(DISTINCT ...) aurait le même effet...
    quelque chose m'échappe...

    Pour le nom des colonnes, il est indispensable de les préfixer du nom de la table (ou de son alias) lorsque deux tables de la requête ont un colonne portant le même nom, afin de pouvoir identifier de quelle colonne il s'agit.

  5. #5
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 793
    Points : 1 327
    Points
    1 327
    Par défaut
    Au niveau du table.champs, ce n'est pas obligatoire, sauf si vous avez un champs avec le même nom dans la table1 et la table2 et que vous vous servez de ce champs.

    Exemples :

    1)
    Table 1 possède les champs c1 et c2
    Table 2 possède les champs t1 et t2

    Pas de nom de champs necessaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Select c1, c2, t1, t2 
    from Table1 
    inner join Table2 on c1 = t1

    2)
    Table 1 possède les champs c1 et c2
    Table 2 possède les champs c1 et c2 également

    Nom de table nécessaire pour lever l’ambigüité :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Select Table1.c1, Table1.c2, Table2.c1, Table2.c2 
    from Table1 
    inner join Table2 on Table1.c1 = Table2.c1
    3)
    Table 1 possède les champs c1 et c2
    Table 2 possède les champs t1 et c2 également

    Nom de table pas nécessaire puisqu'on ne se sert pas de c2 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Select Table1.c1
    from Table1 
    inner join Table2 on Table1.c1 = Table2.t1
    EDIT : J'ai été un peu lent ...

    Par contre cette requête peut effectivement être expliquée par le fait qu'une intervention puisse être faite en plusieurs déplacements.
    Un count(dictinct) n'aurait pas pu être utilisé dans ce cas puisqu'on souhaite ignorer les déplacements, et non faire une selection distincte selon le nombre de déplacements.
    Le Porc est un loup pour le Porc.

  6. #6
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 803
    Points
    30 803
    Par défaut
    Dès qu'une requête porte sur plus d'une table, il est conseillé de préciser le nom de table associé à chaque colonne.
    Il est ainsi plus facile d'identifier immédiatement la source de chaque colonne sans avoir à connaitre la structure des tables en jeu.

    On préférera aussi utiliser des alias courts plutôt que les noms de table complets, pour de simples raison de lisibilité.
    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
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  7. #7
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par cdalo Voir le message
    J'ai certainement du faire une erreur, mais voici un autre exemple qui est correcte (corrigé de mon TD) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT nom, count (refintervention) As Nb
    FROM 
    (SELECT DISTINCT matricule, nom, refintervention
    FROM (membre INNER JOIN déplacement ON membre.matricule = déplacement.refmatricule)
    INNER JOIN intervention 
    ON intervention.idintervention = déplacement. refintervetion )
    GROUP BY nom, matricule ;

    Et bien votre prof a besoin d'un recyclage en SQL !
    Comme dit par d'autres, l'utilisation d'alias pour les tables est fortement recommandé dès qu'il y a plus d'une table dans la requête. Cela facilite l'écriture et la lecture de celle-ci. Il faut ensuite utiliser systématiquement ces alias devant chaque colonne nommée pour savoir facilement de quelle table elle vient.

    Pourquoi faire un GROUP BY nom, matricule alors que la colonne (et pas champ ! ) "matricule" ne figure pas dans le SELECT ?

    Cette requête est probablement suffisante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT m.nom AS nom_membre,
    	COUNT(DISTINCT d.refintervention) AS Nb
    FROM deplacement d
    INNER JOIN membre m ON m.matricule = d.refmatricule
    GROUP BY m.nom
    A vrai dire, je ne cherche pas réellement à savoir l'exactitude mes requêtes, je cherche à comprendre pourquoi certaine fois les DISTINCT sont placés à cet endroit de la requête.
    La requête ci-dessus compte le nombre d'interventions distinctes par membre. Si on ne met pas le DISTINCT, comme il peut, semble t-il, y avoir plusieurs déplacements pour une intervention, on compterait non pas les interventions mais les déplacements.

    Quand DISTINCT est dans un SELECT (et non pas dans un COUNT comme dans la requête ci-dessus), le DISTINCT porte sur toutes les colonnes du SELECT.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT DISTINCT col1, col2
    FROM une_table
    Cette requête donnera tous les couples {col1, col2} différents dans la table. DISTINCT ne porte pas que sur la colonne col1.

    En conséquence, il est inutile de mettre DISTINCT dans le SELECT si la requête est aussi un regroupement (GROUP BY).
    Écrire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT DISTINCT col1, col2
    FROM une_table
    GROUP BY col1, col2
    C'est ceinture et bretelles ! C'est inutile en SQL !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « 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 la suite Linux Mageïa !

  8. #8
    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 CinePhil Voir le message

    Pourquoi faire un GROUP BY nom, matricule alors que la colonne (et pas champ ! ) "matricule" ne figure pas dans le SELECT ?
    Peut-être pour prendre en compte le cas où il y a deux personnes différentes ayant le même nom...

  9. #9
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 793
    Points : 1 327
    Points
    1 327
    Par défaut
    Sauf que si c'est permis que 2 personnes aient le même nom, c'est totalement idiot de ne pas afficher le champs qui permet de les distinguer, ça nous apportera beaucoup de voir :


    Nom / Ventes
    Jean / 5
    René / 5
    René / 7
    René / 25
    John / 2
    John / 72

    Là on sait que John est un mauvais vendeur, alors que John est un très bon vendeur. On est bien avancés.
    Le Porc est un loup pour le Porc.

Discussions similaires

  1. clause Distinct dans requête access
    Par lbar012001 dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 15/02/2007, 10h28
  2. [9i, débutant] Clause DISTINCT sur un seul champ
    Par JYves dans le forum Oracle
    Réponses: 11
    Dernier message: 06/09/2006, 17h08
  3. Clause Distinct ne fonctionne pas su SELECT multiple
    Par fabou3377 dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 04/08/2006, 11h39
  4. Réponses: 3
    Dernier message: 11/04/2006, 10h36
  5. Clause DISTINCT
    Par mathieu77186 dans le forum Langage SQL
    Réponses: 6
    Dernier message: 08/03/2005, 12h37

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