Résolution des résultats en double dans GROUP_CONCAT
avec plusieurs GROUP BY
jointures
Combiner plusieurs clauses GROUP BY
via des LEFT JOIN
et utiliser GROUP_CONCAT
peut conduire à des entrées en double. Cela résulte de la fusion de clés uniques de chaque GROUP BY
, ce qui entraîne une représentation inexacte des données.
Scénario de problème
Considérez cette structure de requête :
<code class="language-sql">SELECT q1.user_id, q1.user_name, q1.score, q1.reputation, SUBSTRING_INDEX(GROUP_CONCAT(q2.tag ORDER BY q2.tag_reputation DESC SEPARATOR ','), ',', 2) AS top_two_tags, SUBSTRING_INDEX(GROUP_CONCAT(q3.category ORDER BY q3.category_reputation DESC SEPARATOR ','), ',', 2) AS category FROM (...) AS q1 LEFT JOIN (...) AS q2 ON q2.user_id = q1.user_id LEFT JOIN (...) AS q3 ON q3.user_id = q1.user_id GROUP BY q1.user_id, q1.user_name, q1.score, q1.reputation</code>
Cette requête vise à récupérer les deux principales balises et catégories pour chaque utilisateur, en supposant des tableaux pour les utilisateurs, les balises, les réputations, post_tag
, les catégories et post_category
. Le problème est le potentiel de doublons comme "css, css" ou "technology, technology" en raison des GROUP BY
joints.
Solutions efficaces
Plusieurs méthodes peuvent éviter ces doublons :
1. Séparez GROUP BY
et INNER JOIN :
<code class="language-sql">-- Separate grouping and joining approach SELECT q1.user_id, q1.user_name, q1.score, q1.reputation, q1.top_two_tags, q2.category FROM (SELECT q1.user_id, q1.user_name, q1.score, q1.reputation, SUBSTRING_INDEX(GROUP_CONCAT(q2.tag ORDER BY q2.tag_reputation DESC SEPARATOR ','), ',', 2) AS top_two_tags FROM (...) AS q1 LEFT JOIN (...) AS q2 ON q2.user_id = q1.user_id GROUP BY q1.user_id, q1.user_name, q1.score, q1.reputation ) AS q1 INNER JOIN (SELECT q1.user_id, SUBSTRING_INDEX(GROUP_CONCAT(q3.category ORDER BY q3.category_reputation DESC SEPARATOR ','), ',', 2) AS category FROM (...) AS q1 LEFT JOIN (...) AS q3 ON q3.user_id = q1.user_id GROUP BY q1.user_id ) AS q2 ON q1.user_id = q2.user_id;</code>
Cette méthode regroupe et concatène d'abord les balises et les catégories séparément, puis joint les résultats à l'aide d'un INNER JOIN
sur user_id
. Cela garantit qu’une seule ligne par utilisateur est produite.
2. Sous-requêtes scalaires :
<code class="language-sql">-- Scalar subquery approach SELECT q1.user_id, q1.user_name, q1.score, q1.reputation, (SELECT SUBSTRING_INDEX(GROUP_CONCAT(q2.tag ORDER BY q2.tag_reputation DESC SEPARATOR ','), ',', 2) FROM (...) AS q2 WHERE q2.user_id = q1.user_id ), (SELECT SUBSTRING_INDEX(GROUP_CONCAT(q3.category ORDER BY q3.category_reputation DESC SEPARATOR ','), ',', 2) FROM (...) AS q3 WHERE q3.user_id = q1.user_id ) FROM (...) AS q1;</code>
Cela utilise des sous-requêtes dans la liste SELECT
pour récupérer les principales balises et catégories pour chaque utilisateur individuellement, évitant ainsi l'ambiguïté GROUP BY
.
La clé est d'éviter de concaténer directement les données de plusieurs tables jointes au sein d'un seul appel GROUP_CONCAT
lors de l'utilisation de GROUP BY
sur plusieurs tables. La solution choisie dépend de la structure spécifique de la base de données et des considérations de performances. L'objectif est de produire des résultats précis et sans doublon.
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!