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

Développement SQL Server Discussion :

Peut-on remplacer une sous-requête par une jointure ?


Sujet :

Développement SQL Server

  1. #1
    Membre du Club
    Homme Profil pro
    informatique de gestion
    Inscrit en
    Janvier 2011
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : informatique de gestion

    Informations forums :
    Inscription : Janvier 2011
    Messages : 92
    Points : 67
    Points
    67
    Par défaut Peut-on remplacer une sous-requête par une jointure ?
    VOILA je lance ce post pour savoir dans quelles conditions il est préférable de choisir une sous-requête ou une jointure de table ....
    Merci

  2. #2
    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 789
    Points
    30 789
    Par défaut
    La réponse est : "ça dépend".
    Quelle type de sous-requête ? Une table dérivée, une sous-requête corrélée ?
    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.

  3. #3
    Membre du Club
    Homme Profil pro
    informatique de gestion
    Inscrit en
    Janvier 2011
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : informatique de gestion

    Informations forums :
    Inscription : Janvier 2011
    Messages : 92
    Points : 67
    Points
    67
    Par défaut
    Si je comprend bien le choix dépend du résultat demandé ?????

  4. #4
    Invité
    Invité(e)
    Par défaut
    Montrez-nous tout de suite votre requête ou un exemple, ça évitera de rester sur un stade purement théorique.

  5. #5
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 761
    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 761
    Points : 52 547
    Points
    52 547
    Billets dans le blog
    5
    Par défaut
    Effectivement, ça dépend....

    Exemples classiques :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    --> nom, prénom de la plus jeune personne
    SELECT nom, prenom
    FROM   T_PERSONNE
    WHERE  date_naissance =
           (SELECT MAX(date_naissance) 
            FROM   T_PERSONNE);
    Pas possible en jointure directe sans une sous requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT nom, prenom
    FROM   T_PERSONNE AS P
           INNER JOIN (SELECT MAX(date_naissance) AS date_max 
                       FROM   T_PERSONNE) AS M
                 ON P.date_naissance = M.date_max;
    La requête suivante donne des résultats faux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT TOP 1 nom, prenom
    FROM   T_PERSONNE AS P
    ORDER BY date_naissance DESC
    Devinez pourquoi !


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    --> liste des homonymes
    SELECT *
    FROM   T_PERSONNE
    WHERE  prenom IN (SELECT prenom
                   FROM   T_PERSONNE
                   GROUP  BY prenom
                   HAVING COUNT(*) > 1);
    On peut la remplacer par une jointure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT p1.*
    FROM   T_PERSONNE AS P1
           JOIN T_PERSONNE AS P2
                ON P1.LA_CLEF <> P2.LA_CLEF
                AND P1.prenom = P2.prenom

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    --> client n'ayant pas été facturé en 2015
    SELECT *
    FROM   T_CLIENT AS C
    WHERE  NOT EXISTS
              (SELECT 1
               FROM   T_FACTURE AS F
               WHERE  C.CLI_ID = F.CLI_ID
                 AND  YEAR(FAC_DATE) = 2014);
    Remplaçable par une semi anti-jointure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT *
    FROM   T_CLIENT AS C
           LEFT OUTER JOIN T_FACTURE AS F
           ON C.CLI_ID = F.CLI_ID 
              AND YEAR(FAC_DATE) = 2014
    WHERE  F.CLI_ID IS NULL;
    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/ * * * * *

  6. #6
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 149
    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 149
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    J'aurais tendance à généraliser (même si ce n'est pas exact) que généralement :
    - si la sous-requête contient une fonction d’agrégation dans la clause SELECT, alors c'est pas possible (ou plus difficile)
    - sinon on peut avec une jointure plus ou moins évidente
    En général :
    IN/EXISTS => INNER JOIN
    NOT IN/ NOT EXISTS => LEFT OUTER JOIN ... WHERE pk is NULL
    HAVING COUNT(*)/SUM()... => Jointure carabinée
    On ne jouit bien que de ce qu’on partage.

  7. #7
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 761
    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 761
    Points : 52 547
    Points
    52 547
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    J'aurais tendance à généraliser (même si ce n'est pas exact) que généralement :
    - si la sous-requête contient une fonction d’agrégation dans la clause SELECT, alors c'est pas possible (ou plus difficile)
    Non, ce n'est JAMAIS possible.

    Mais il y a deux autres cas :
    1) filtrage de fonction fenêtrées
    2) requêtes récursives.

    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/ * * * * *

  8. #8
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    Effectivement, ça dépend....

    La requête suivante donne des résultats faux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT TOP 1 nom, prenom
    FROM   T_PERSONNE AS P
    ORDER BY date_naissance DESC
    Devinez pourquoi !
    Parce que tu n'as pas pensé à WITH TIES. lol

    Citation Envoyé par SQLpro Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    --> liste des homonymes
    SELECT *
    FROM   T_PERSONNE
    WHERE  nom IN (SELECT prenom
                   FROM   T_PERSONNE
                   GROUP  BY prenom
                   HAVING COUNT(*) > 1);
    Y a deux erreurs, là.

    1) Faute de frappe (nom <> prenom)
    2) Produit cartésien = probablement plus de lignes
    Most Valued Pas mvp

  9. #9
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 761
    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 761
    Points : 52 547
    Points
    52 547
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par Sergejack Voir le message
    Parce que tu n'as pas pensé à WITH TIES. lol
    Donne aussi des résultats faux !

    1) Faute de frappe (nom <> prenom)
    Je corrige
    2) Produit cartésien = probablement plus de lignes
    Quel produit cartésien ? le IN est une forme de jointure....

    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/ * * * * *

  10. #10
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    Donne aussi des résultats faux !
    Comment ça pourrait être faux ?
    C'est exactement le même résultat que le JOIN / MAX.

    Citation Envoyé par SQLpro Voir le message
    Quel produit cartésien ? le IN est une forme de jointure....
    J'avais mal cité. Je faisais référence à ton

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT p1.*
    FROM   T_PERSONNE AS P1
           JOIN T_PERSONNE AS P2
                ON P1.LA_CLEF <> P2.LA_CLEF
                AND P1.prenom = P2.prenom
    Most Valued Pas mvp

  11. #11
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 761
    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 761
    Points : 52 547
    Points
    52 547
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par Sergejack Voir le message
    Comment ça pourrait être faux ?
    C'est exactement le même résultat que le JOIN / MAX.

    J'avais mal cité. Je faisais référence à ton

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT p1.*
    FROM   T_PERSONNE AS P1
           JOIN T_PERSONNE AS P2
                ON P1.LA_CLEF <> P2.LA_CLEF
                AND P1.prenom = P2.prenom
    Produit cartésien c'est CROSS JOIN. Là il s'agit d'une non équi jointure, plus généralement appelé thêta jointure...
    http://fr.wiktionary.org/wiki/th%C3%AAta-jointure
    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/ * * * * *

  12. #12
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    Produit cartésien c'est CROSS JOIN. Là il s'agit d'une non équi jointure, plus généralement appelé thêta jointure...
    http://fr.wiktionary.org/wiki/th%C3%AAta-jointure
    A +
    Tu as raison, produit cartésien n'était pas la bonne expression.
    Il n’empêche que ton query est faux et peux renvoyer plusieurs fois la même lignes.


    Quant à l'emploie de WITH TIES, je te laisse l'essayer puisque t'es persuadé que c'est faux sans avoir pu expliquer en quoi ^^

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    SELECT TOP 1 WITH TIES nom, prenom 
    FROM   T_PERSONNE AS P
    ORDER BY date_naissance DESC
    Most Valued Pas mvp

  13. #13
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 761
    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 761
    Points : 52 547
    Points
    52 547
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par Sergejack Voir le message
    ...Quant à l'emploie de WITH TIES, je te laisse l'essayer puisque t'es persuadé que c'est faux sans avoir pu expliquer en quoi ^^

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    SELECT TOP 1 WITH TIES nom, prenom 
    FROM   T_PERSONNE AS P
    ORDER BY date_naissance DESC
    Parce que la clause ORDER BY n'est pas une opération relationnelle. C'est une clause cosmétique. Elle assure le tri du résultat un fois le résultat calculé. Elle doit donc être totalement indépendante des opérations relationnelles que la requête effectue. Or si l'utilisateur veut trier le résultat sur nom, prénom, alors le résultat ne sera pas celui attendu !
    Il faudrait alors faire une sous requête ce qui impliquerait deux opérations de tri dans le plan d'exécution, donc un cout exorbitant !

    Toutes ces pseudo clause TOP ou LIMIT sont des fumisteries... Soit elle donnent des résultats incohérent, soient elles empêchent certaines autres opérations et au final s'avèrent plus couteuses que d'utiliser les opérateurs SQL normalisés.

    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/ * * * * *

  14. #14
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut
    Je ne suis absolument pas d'accord avec cette vision du "Il ne faut pas l'utiliser où ça marche parce ailleurs ça ne marche pas".
    S'il faut trier par autre chose, si il faut joindre d'autres tables, finir avec un query dont la taille en caractères est un multiple de 42, ... alors là on peut ranger l'idée au placard.

    En attendant de telles conditions, ORDER BY + TOP amènent déjà SQL Server à faire bon usage des indexes.
    Quand le résultat est bon* et les performances sont bonnes, faut pas tortiller du cul sous prétexte que la pratique ne rend pas d'éloge à une théorie laborieuse XD

    L'essentiel est d'obtenir un résultat correct et (le plus) rapidement.

    * Un résultat trié n'est pas un mauvais résultat

    PS: je trouve grâve de condamner TOP + ORDER BY, t'as l'air de complètement oublié que si un tri doit être fait dans une gamme de logiciels, il faut être bête pour ne pas le faire là où des indexes le rendent rapide.
    Most Valued Pas mvp

Discussions similaires

  1. Réponses: 11
    Dernier message: 11/02/2013, 14h23
  2. Remplacer une sous-requête par une jointure
    Par MPQuatre dans le forum Requêtes
    Réponses: 6
    Dernier message: 05/12/2007, 17h28
  3. Réponses: 3
    Dernier message: 05/01/2007, 15h50
  4. Remplacer une sous chaîne par une autre
    Par Erakis dans le forum Général JavaScript
    Réponses: 15
    Dernier message: 10/11/2006, 09h16
  5. Réponses: 3
    Dernier message: 18/05/2003, 00h16

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