Conseils pour éviter la multiplication des valeurs SUM lors de l'utilisation de fonctions d'agrégation pour joindre des tables dans MySQL
Lors de la combinaison de plusieurs opérations de jointure dans une requête MySQL, l'utilisation de fonctions d'agrégation telles que SUM peut conduire à des résultats inattendus. En effet, le produit cartésien de ligne de la table de jointure multiplie les résultats additionnés, ce qui entraîne des résultats inexacts.
Supposons qu'il existe un exemple dans lequel deux requêtes sont initialement utilisées pour récupérer les valeurs SUM de différentes tables. La requête 1 calcule le temps de conduite total pour un employé spécifique pendant une plage de dates spécifique, tandis que la requête 2 calcule le temps de travail total pour le même employé pendant la même période.
Essayer de combiner ces requêtes en une seule requête de jointure entraînera des sommes incorrectes. En effet, l'opération JOIN crée le produit cartésien des lignes du tableau bhds_timecard
et bhds_mileage
. En conséquence, les valeurs SUM pour le temps de conduite et le temps de travail sont multipliées par le nombre de lignes correspondantes dans chaque tableau.
Pour résoudre ce problème, vous pouvez utiliser une sous-requête pour calculer la valeur SUM avant de joindre les tables. En déplaçant l'opération SUM dans une sous-requête distincte, vous pouvez empêcher le produit cartésien et obtenir des résultats précis.
Ce qui suit est une requête améliorée à l'aide de sous-requêtes :
<code class="language-sql">SELECT last_name, first_name, DATE_FORMAT(LEAST(mil_date, tm_date), '%m/%d/%y') AS dates, total, minutes FROM bhds_teachers AS i LEFT JOIN ( SELECT ds_id, YEARWEEK(mil_date) AS week, MIN(mil_date) AS mil_date, SUM(drive_time) AS minutes FROM bhds_mileage WHERE mil_date BETWEEN '2016-04-11' AND '2016-04-30' AND bhds_mileage.ds_id = 5 GROUP BY ds_id, week ) AS m ON m.ds_id = i.ds_id LEFT JOIN ( SELECT ds_id, YEARWEEK(tm_date) AS week, MIN(tm_date) AS tm_date, SUM(tm_hours) AS total FROM bhds_timecard WHERE tm_date BETWEEN '2016-04-11' AND '2016-04-30' AND bhds_timecard.ds_id = 5 GROUP BY ds_id, week ) AS t ON t.ds_id = i.ds_id AND t.week = m.week;</code>
Dans cette requête :
m
Calcule le temps de conduite total regroupé par numéro d'employé et par semaine. t
Calcule le total des heures travaillées regroupées par numéro d'employé et par semaine. bhds_teachers
avec les sous-requêtes m
et t
. En conséquence, la requête récupère le nom, le prénom, la date, le temps total de travail et le temps total de conduite du salarié et la période spécifiée sans problème de multiplication des valeurs SOMME.
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!