JOIN permet de combiner plusieurs tables dans une seule requête SELECT en fonction d'une condition spécifique, généralement via le mot clé ON. Une sous-requête (ou requête imbriquée) est une requête insérée à l'intérieur d'une autre requête. JOIN fonctionne mieux pour combiner de grandes tables avec de bons index, il est plus transparent pour l'optimiseur et s'exécute généralement plus rapidement. Les sous-requêtes sont pratiques lorsqu'il est nécessaire de calculer des agrégats ou lorsqu'il existe des conditions impossibles à réaliser via JOIN (par exemple, des requêtes corrélées).
Exemple de JOIN :
SELECT employees.name, departments.name FROM employees JOIN departments ON employees.dept_id = departments.id;
Exemple de sous-requête :
SELECT name FROM employees WHERE dept_id IN ( SELECT id FROM departments WHERE location = 'Moscow' );
“Est-il vrai que l'utilisation des sous-requêtes est toujours plus lente que l'utilisation de JOIN ?”
Réponse : Non, pas toujours ! Des sous-requêtes bien écrites sont souvent transformées par l'optimiseur en JOIN internes. De plus, parfois les sous-requêtes peuvent être plus efficaces — par exemple, lorsque la requête externe travaille avec un petit ensemble de données et que la sous-requête retourne des résultats déjà agrégés.
Exemple :
SELECT name, salary FROM employees WHERE salary > (SELECT AVG(salary) FROM employees);
Cette sous-requête sera exécutée une seule fois.
Histoire
Dans un grand projet, des sous-requêtes imbriquées étaient utilisées pour un rapport au lieu de JOIN. Avec l'augmentation du volume de données, la requête a commencé à prendre plusieurs minutes au lieu de secondes. Après avoir remplacé les sous-requêtes par des JOIN, les performances ont été multipliées par 10.
Histoire
Dans un projet, un analyste a réécrit une requête avec GROUP BY en sous-requête, sans se rendre compte que cela a entraîné des doublons au niveau de JOIN. Cela a conduit à des données incorrectes dans les rapports — les sommes étaient surestimées à cause du produit cartésien.
Histoire
L'utilisation d'une sous-requête corrélée dans une boucle externe (pour chaque ligne) a entraîné une dégradation complète des performances lors de l'augmentation de la taille de la table. Nous avons décidé d'utiliser JOIN avec agrégation — le temps de traitement des requêtes est passé de plusieurs heures à quelques minutes.