Pièges et solutions pour les jointures gauches multiples SQL qui conduisent à des résultats de comptage incorrects
Lors de l'utilisation de SQL, si plusieurs jointures gauches ne sont pas gérées correctement, des résultats inattendus peuvent se produire. Considérez la requête suivante :
<code class="language-sql">SELECT t1."id" AS "User ID", t1.account_balance AS "Account Balance", count(t2.user_id) AS "# of grocery visits", count(t3.user_id) AS "# of fishmarket visits" FROM users t1 LEFT OUTER JOIN grocery t2 ON (t2.user_id=t1."id") LEFT OUTER JOIN fishmarket t3 ON (t3.user_id=t1."id") GROUP BY t1.account_balance,t1.id ORDER BY t1.id</code>
Cette requête tente de compter le nombre de visites à deux tables liées users
et grocery
pour chaque utilisateur de la table fishmarket
. Cependant, en raison de la nature des jointures gauches, cela produit des résultats incorrects.
Malentendus sur les jointures à gauche
En SQL, les jointures s'effectuent de gauche à droite. Dans cette requête, une jointure gauche entre users
et grocery
est d'abord effectuée. Cela a pour résultat que chaque enregistrement d'utilisateur est connecté à son enregistrement d'achat d'épicerie correspondant. Ensuite, une deuxième jointure gauche est effectuée entre le premier résultat de jointure et fishmarket
, ce qui signifie que chaque enregistrement d'utilisateur avec un enregistrement d'achat d'épicerie sera ensuite joint à son enregistrement d'achat au marché aux poissons correspondant.
Multiplication au lieu d'addition
Une conséquence involontaire de ce traitement séquentiel est que les comptes d'accès de grocery
et fishmarket
sont multipliés plutôt qu'additionnés. Par exemple, si un utilisateur effectuait 3 visites à l'épicerie et 4 visites au marché aux poissons, la requête donnerait 12 visites au lieu des 7 attendues.
Solution : utiliser des sous-requêtes pour l'agrégation
Pour corriger cela, nous devons nous assurer d'effectuer une agrégation (compte) du nombre de visites avant de joindre les tables. Ceci peut être réalisé en utilisant une sous-requête :
<code class="language-sql">SELECT u.id , u.account_balance , g.grocery_visits , f.fishmarket_visits FROM users u LEFT JOIN ( SELECT user_id, count(*) AS grocery_visits FROM grocery GROUP BY user_id ) g ON g.user_id = u.id LEFT JOIN ( SELECT user_id, count(*) AS fishmarket_visits FROM fishmarket GROUP BY user_id ) f ON f.user_id = u.id ORDER BY u.id;</code>
Cette requête modifiée regroupe les visites dans une sous-requête, puis joint les résultats agrégés à la table users
, garantissant que les visites ne sont pas accidentellement multipliées.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!