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 :

Count Distinct sous requête


Sujet :

Langage SQL

  1. #1
    BiM
    BiM est déconnecté
    Expert éminent sénior
    Avatar de BiM
    Femme Profil pro
    Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT
    Inscrit en
    Janvier 2005
    Messages
    7 796
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT

    Informations forums :
    Inscription : Janvier 2005
    Messages : 7 796
    Points : 10 765
    Points
    10 765
    Par défaut Count Distinct sous requête
    Bonjour,

    Je me casse la tête depuis 2h sur une optimisation de requête et je ne comprends pas un comportement.

    La requête d'origine est :
    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
    SELECT count(*)
    FROM (
    	SELECT count(*) as c 
    	FROM
    		Physicians t0
    		LEFT JOIN table1 t1 ON t1.Id = t0.Speciality
    		INNER JOIN table2 t2 ON t2.Id = t0.Degree
    		INNER JOIN table3 t3 ON t3.Id = t0.WebSite
    		INNER JOIN table4 t4 ON t4.WebSite = t0.WebSite
    	WHERE
    		t3.DirectoryAndRobotStatus = 1 AND
    		t3.OnlineStatus = 1 AND
    		t3.BlockStatus = 0
    	GROUP BY
    		t0.Login, t0.Degree, t0.OtherDegree, t0.Firstname, t0.Middlename, t0.Lastname,
    		t4.AddressNumber, t4.AddressStreet, t4.AddressMore, t4.AddressPostCode, t4.AddressCity, t4.Name,
    		t1.Specialist, t3.DNS, t3.OnlineStatus, t3.DirectoryAndRobotStatus, t3.BlockStatus, t2.Label
    ) as t

    Je trouve le même résultat avec cette requête :
    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
    select count(*) from (	
    	SELECT DISTINCT
    		t0.Login, t0.Degree, t0.OtherDegree, t0.Firstname, t0.Middlename, t0.Lastname,
    		t4.AddressNumber, t4.AddressStreet, t4.AddressMore, t4.AddressPostCode, t4.AddressCity, t4.Name,
    		t1.Specialist, t3.DNS, t3.OnlineStatus, t3.DirectoryAndRobotStatus, t3.BlockStatus, t2.Label
    	FROM
    		Physicians t0
    		LEFT JOIN table1 t1 ON t1.Id = t0.Speciality
    		INNER JOIN table2 t2 ON t2.Id = t0.Degree
    		INNER JOIN table3 t3 ON t3.Id = t0.WebSite
    		INNER JOIN table4 t4 ON t4.WebSite = t0.WebSite
    	WHERE
    		t3.DirectoryAndRobotStatus = 1 AND
    		t3.OnlineStatus = 1 AND
    		t3.BlockStatus = 0
    ) as t

    Mais pas avec :
    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
    SELECT COUNT(DISTINCT
    	t0.Login, t0.Degree, t0.OtherDegree, t0.Firstname, t0.Middlename, t0.Lastname,
    	t4.AddressNumber, t4.AddressStreet, t4.AddressMore, t4.AddressPostCode, t4.AddressCity, t4.Name,
    	t1.Specialist, t3.DNS, t3.OnlineStatus, t3.DirectoryAndRobotStatus, t3.BlockStatus, t2.Label)
    FROM
    	Physicians t0
    	LEFT JOIN table1 t1 ON t1.Id = t0.Speciality
    	INNER JOIN table2 t2 ON t2.Id = t0.Degree
    	INNER JOIN table3 t3 ON t3.Id = t0.WebSite
    	INNER JOIN table4 t4 ON t4.WebSite = t0.WebSite
    WHERE
    	t3.DirectoryAndRobotStatus = 1 AND
    	t3.OnlineStatus = 1 AND
    	t3.BlockStatus = 0

    Savez-vous pourquoi ?

    Merci.

  2. #2
    Membre émérite Avatar de lola06
    Femme Profil pro
    Consultante en Business Intelligence
    Inscrit en
    Avril 2007
    Messages
    1 316
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 37
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultante en Business Intelligence
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2007
    Messages : 1 316
    Points : 2 520
    Points
    2 520
    Par défaut
    Il n'y a pas d'erreur ?

    On m'a toujours dit qu'on ne pouvait mettre qu'une colonne ou une * dans un count...

    P.S : pensez à indiquer votre SGBD.

  3. #3
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    nan le count(distinct ...) ou count(ma_col) fonctionne.

    Par contre je ne vois pas le problème, pour moi la 3eme requête devrai retourner le même résultat que les 2 1ere.

    A moins qu'il y ai des null qui trainnent ...


    Sinon, si on parle d'optimisation, quel est le but de la requête ?

    Car là, faire un group by sur N colonnes pour ensuite ne vouloir compter que des résutlats distinct implique surement un oubli de l'utilisation de EXISTS

  4. #4
    BiM
    BiM est déconnecté
    Expert éminent sénior
    Avatar de BiM
    Femme Profil pro
    Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT
    Inscrit en
    Janvier 2005
    Messages
    7 796
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT

    Informations forums :
    Inscription : Janvier 2005
    Messages : 7 796
    Points : 10 765
    Points
    10 765
    Par défaut
    Bonjour,

    Merci pour vos réponses.

    Je suis sur MySQL 5.5, je pensais que ça ne nous avancerait pas vraiment dans la conversation puisque c'est de l'optimisation de requêtes SQL (qui est à priori (ou presque) un standard).

    J'ai du mal à voir d'où vient la différence de résultat entre les requêtes 1 et 2 et la requête 3 vu la volumétrie de données (Ca me donne des chiffres du type 19 000 résultats si vous voyez ce que je veux dire ).

    @punkoff : Peux-tu m'expliquer ton idée du EXISTS ? Visiblement, ça implique des requêtes imbriquées. Or j'aimerais pouvoir faire ma requête sans requêtes imbriquées justement d'où la tentative de simplification de la requête en question.

    Si vous avez des idées, je suis preneuse.
    Merci.

  5. #5
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Pourquoi éviter des requêtes imbriqués ?
    La vous multipliez les résultat avec les jointures pour ensuite les restreindres.


    Tant que vous n'expliquerez pas un peu plus le but de la requête je ne pourrai pas me positionner plus que ça.

  6. #6
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    On se demande en effet à quoi servent toutes ces jointures !

    Les conditions du WHERE ne portent que sur le table3 (j'espère pour vous qu'elle ne s'appelle pas comme ça !) et vous ne voulez semble t-il que compter les lignes. Une seule jointure suffirait.

    Dites-nous ce que vous cherchez à obtenir et donnez-nous la structure des tables ainsi qu'un petit jeu de données, ce sera plus facile pour vous aider.

  7. #7
    Membre chevronné
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Février 2012
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Distribution

    Informations forums :
    Inscription : Février 2012
    Messages : 652
    Points : 1 878
    Points
    1 878
    Par défaut
    Simpliez la requête dans un premier temps, évitez le LEFT JOIN qui est juste contre-performant

  8. #8
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    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 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Le LEFT JOIN était contre-performant en 1992 quand seul Ingre existait et commençait tout juste à supporter les jointures hein...

    Au contraire, un LEFT JOIN est aujourd'hui souvent plus rapide qu'un INNER JOIN !

    Dans tous les cas, ce n'est pas les performances qui imposent d'utiliser LEFT, RIGHT, CROSS ou INNER, mais simplement la structure des données et le résultat attendu : elles ont toutes un comportement tout à fait différent et ne doivent pas être remplacées les unes par les autres sans se poser un minimum de questions.

  9. #9
    Membre chevronné
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Février 2012
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Distribution

    Informations forums :
    Inscription : Février 2012
    Messages : 652
    Points : 1 878
    Points
    1 878
    Par défaut
    Entre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT count(*)
    FROM table
    Et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT count(*)
    FROM table
      LEFT JOIN Table2
        ON table.chp = table2.chp
    Le résultat est le même et la jointure ne sert strictement à rien
    (A condition que la relation ne soit pas 1 - n)

  10. #10
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    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 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Pour en revenir à la requête : en plus de la structure de la base et un jeu de données, merci aussi de nous communiquer quelques règles.

    Par exemple "table1" semble la table des spécialité.

    On a une jointure à partir de physicians à partir d'un champ "speciality"
    => Un physicians a donc une et une seule spécialité.
    On fait le distinct par "table1.specialist"
    => Peut-il y avoir un même table1.specialist pour des table1.id ? Si c'est impossible, alors autant faire le distinct sur physicians.speciality et virer la jointire sur table1.

  11. #11
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    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 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Scriuiw > Comme tu dis "à condition que"

    Aussi :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT count(distinct table.champ1)
    FROM TABLE

    Et différent de :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT count(distinct table.champ1, table2.champ2)
    FROM TABLE
      LEFT JOIN Table2
        ON TABLE.chp = table2.chp

    Et ce, quelle que soit la cardinalité entre TABLE et TABLE2

  12. #12
    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 388
    Points
    18 388
    Par défaut
    Ça fonctionne count(distinct c1, c2, ...) sur MySQL ?

  13. #13
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345

  14. #14
    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 388
    Points
    18 388
    Par défaut
    Ça n'existe pas chez les autres éditeurs, d'où ma question !

  15. #15
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Mon jugement est peut-être biaisé dans ce cas.

    Sur PostGreSql un tel cas fonctionne aussi (db2 non et je suppose qu'Oracle non plus..)

  16. #16
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    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 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Je confirme, count(distinct liste de champs) ne fonctionne pas avec Oracle

  17. #17
    Membre émérite Avatar de lola06
    Femme Profil pro
    Consultante en Business Intelligence
    Inscrit en
    Avril 2007
    Messages
    1 316
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 37
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultante en Business Intelligence
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2007
    Messages : 1 316
    Points : 2 520
    Points
    2 520
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Je confirme, count(distinct liste de champs) ne fonctionne pas avec Oracle
    Merci pour la confirmation.
    Mon premier post n'était pas si hors sujet que ça...

  18. #18
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    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 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Sur le coup j'ai pensé comme toi, mais vu la réaction de punkoff, je me suis dit qu'on était dans le faux

    Donc en tout cas, si seul MySQL supporte le bignou, il ne faut surtout pas l'utiliser car :
    - vu que c'est pas standard, ça va être la merde à maintenir
    - de toute façon c'est buggé (la preuve)

Discussions similaires

  1. COUNT dans sous-requête
    Par Maryy dans le forum Langage SQL
    Réponses: 4
    Dernier message: 14/02/2014, 17h44
  2. Count et sous requêtes
    Par mico2 dans le forum Langage SQL
    Réponses: 4
    Dernier message: 16/06/2010, 23h37
  3. Requête qui cumule un "count distinct"
    Par jerjerrod dans le forum SQL
    Réponses: 18
    Dernier message: 16/06/2009, 14h37
  4. Réponses: 1
    Dernier message: 22/12/2008, 10h15
  5. problème requête - 2 tables - count - distinct
    Par avironix2 dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 27/12/2007, 10h16

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