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 :

Mettre DISTINCT dans un COUNT est-il normalisé ?


Sujet :

Langage SQL

  1. #1
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 414
    Points : 871
    Points
    871
    Par défaut Mettre DISTINCT dans un COUNT est-il normalisé ?
    bonjour,

    Je devais compter le nombre de client ayant une commande, alors j'ai fait cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT count(id_client) from commandes
    biensur ça m'a retourné un chiffre faux si un client avait plusieurs commandes.
    Si je n'avais pas à les compter, mais juste les lister, j'aurai fait cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT DISTINCT id_client from commandes
    .
    Avant si j'étais en php j'aurai mis le résultat dans un tableau et compter.

    Mais là (par fleme d'été), et par curiosité, j'ai testé de mettre le DISTINCT directement dans le count et miracle ça fonctionne !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT count( DISTINCT id_client) from commandes
    je suis assez étonné car en 20ans de SQL je l'avais jamais vu, ni appris ni lu.
    alors ...?

    je suis sous Postgresql, donc peut-être que c'est une spécificité de ce sgbb mais ça m'intrigue. je ne trouve aucune doc dessus sur la place du DISTINCT dans une requête SQL.

    qu'en savez-vous ?

  2. #2
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 166
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Février 2010
    Messages : 4 166
    Points : 7 418
    Points
    7 418
    Billets dans le blog
    1
    Par défaut
    Oui, ça marche parfaitement, et c'est standard.

    En revanche, count(distinct client_id, age_capitaine) ne fonctionne pas. Et c'est bien dommage quand tu veux compter les tuples différents.
    On ne jouit bien que de ce qu’on partage.

  3. #3
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 848
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 848
    Points : 52 964
    Points
    52 964
    Billets dans le blog
    6
    Par défaut
    Tous les opérateurs d'agrégation doivent accepter DISTINCT et ALL
    En particulier :
    MIN, MAX, AVG, SUM, COUNT, EVERY, SOME, ANY....

    ALL étant par défaut.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  4. #4
    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 046
    Points
    34 046
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    EVERY, SOME, ANY....
    Tiens ! Je ne les connais pas ceux là !
    Il va falloir que je replonge dans ton bouquin Fred !

    Ne les ayant jamais vus, je suppose qu'ils n'existent pas chez MySQL ?
    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 !

  5. #5
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 453
    Points : 18 383
    Points
    18 383
    Par défaut
    Il y a de fortes chances que vous les utilisiez sans le savoir, on s'en sert lorsqu'on fait des requêtes de comparaison à d'autre requêtes.

    Par exemple, si je ne veux travailler que sur la date la plus grande, on peut filtrer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE madate >= (select MAX(madate)...
    Qui est équivalente à la requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE madate >= ANY (select madate...
    Il me semble bien que ça figure dans les articles de SQLPro, mais en pratique c'est peu usité.

  6. #6
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 414
    Points : 871
    Points
    871
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Oui, ça marche parfaitement, et c'est standard.

    En revanche, count(distinct client_id, age_capitaine) ne fonctionne pas. Et c'est bien dommage quand tu veux compter les tuples différents.
    pas grave, tu n'as qu'à concatener tes 2 champs comme ça ton DISTINCT passera! ça reviendra au même que ce que tu as besoin (pense tout de même à bien faire en sorte que toutes les valeurs des champs aient le même nombre de digit, sinon 12 ne sera pas vu comme 0000100002)

  7. #7
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 453
    Points : 18 383
    Points
    18 383
    Par défaut
    Citation Envoyé par Michael REMY Voir le message
    tu n'as qu'à concatener tes 2 champs comme ça ton DISTINCT passera! ça reviendra au même que ce que tu as besoin
    Surtout pas !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT count(DISTINCT c1 || c2) AS nb_dist
      FROM ( select 'ab' as c1, 'cd' as c2 from dual union all
             select 'abc'     , 'd'        from dual);
     
    NB_DIST
    -------
          1

  8. #8
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 414
    Points : 871
    Points
    871
    Par défaut
    Waldar....

    vous avez cherché la réponse qui ne prend pas en compte ma remarque : chaque champs doit être remis à la même taille de caractère (avec lpad).

    dans votre exemple, ça aurait du donner (je considère le _ comme caractère de remplissement) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT count(DISTINCT c1 || c2) AS nb_dist
      FROM ( SELECT '_ab' AS c1, '_cd' AS c2 FROM dual union ALL
             SELECT 'abc'     , '__d'        FROM dual);
     
    NB_DIST
    -------
          2

  9. #9
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 166
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Février 2010
    Messages : 4 166
    Points : 7 418
    Points
    7 418
    Billets dans le blog
    1
    Par défaut
    Je suis bien d'accord qu'on peut s'en sortir avec ce genre de bidouilles...

    Mais le problème, c'est quand même que les concaténations / conversions de type / lpad et autres joyeusetés, c'est des perfs killers.

    A mon avis, un sous-select sera plus pertinant :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select count(*)
    from (
      select distinct client_id, age_du_capitaine
      from matable
    );

    Seul détail : un distinct dans une sous-requête, c'est uber crade.
    (mais pas autant que des concaténation/conversion/lpad dans tous les sens ^^)

    Code sql : 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
    18
    19
    20
     
     
    with ma_table as
    (
      select 1 id, 1 client_id, 1 age_du_capitaine from dual union all
      select 2, 1, 1 from dual union all
      select 3, 2, 1 from dual union all
      select 4, 3, 1 from dual union all
      select 5, 3, 1 from dual union all
      select 6, 3, 2 from dual union all
      select 7, 4, 1 from dual union all
      select 8, 4, 2 from dual union all
      select 9, 4, 2 from dual union all
      select 10, 5, 1 from dual union all
      select 11, 5, 1 from dual
    )
    select count(*) from (
      select distinct client_id, age_du_capitaine
      from ma_table
    );
    On ne jouit bien que de ce qu’on partage.

  10. #10
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 453
    Points : 18 383
    Points
    18 383
    Par défaut
    Michael REMY> C'est vrai j'ai lu trop vite et raté la partie padding, mais StringBuilder l'a bien dit, côté performance c'est pas tiptop.

    StringBuilder> pourquoi serait-ce "crade" ? Si c'est la requête qui répond au besoin...

  11. #11
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 414
    Points : 871
    Points
    871
    Par défaut
    quand vous parlez de performance, vous sous-entendez quoi ?

    - consommation de mémoire, de cache, de piles..etc

    ou

    - consommation CPU ?

    à mon avis, ma solution consomme du cpu mais pas de mémoire, alors que la tienne fait l'inverse (car utilise un jeu de données ou une clause supplémentaire)


    (mais pas autant que des concaténation/conversion/lpad dans tous les sens ^^)
    rohh , avec une VIEW et hop c'est transparent à l'oeil !
    puis dans mon cas il y a des concat et des lapd si on manipule des strings (ce que je fais pas), mais plutôt des int. Et on remplace le couple concat+lap par une simple multiplication judicieuse et là c'est une Ferrari le process !

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

Discussions similaires

  1. [XL-2007] Mettre variables dans une matrice qui est utilisée par une fonction
    Par Agalis dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 03/04/2012, 09h08
  2. Une liste (ul) dans un paragraphe (p). Est ce normalisé?
    Par RunCodePhp dans le forum Mise en page CSS
    Réponses: 4
    Dernier message: 30/03/2010, 16h35
  3. [AC-2003] Comment mettre en majuscule ce qui est saisi dans l'InputBox?
    Par spacesheep dans le forum IHM
    Réponses: 4
    Dernier message: 18/11/2009, 22h01
  4. Réponses: 2
    Dernier message: 21/02/2008, 18h39
  5. Count Distinct dans un état
    Par Alfador dans le forum IHM
    Réponses: 3
    Dernier message: 20/06/2007, 20h04

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