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
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
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.
Si je comprend bien le choix dépend du résultat demandé ?????
Montrez-nous tout de suite votre requête ou un exemple, ça évitera de rester sur un stade purement théorique.
Effectivement, ça dépend....
Exemples classiques :
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
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);
La requête suivante donne des résultats faux :
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;
Devinez pourquoi !
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
On peut la remplacer par une jointure :
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);
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
Remplaçable par une semi anti-jointure :
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);
A +
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;
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/ * * * * *
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.
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/ * * * * *
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/ * * * * *
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
Most Valued Pas mvp
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/ * * * * *
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
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/ * * * * *
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
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager