MySQL : Extraire l'entrée finale de chaque groupe de données
Une opération fréquente de base de données consiste à récupérer l'enregistrement le plus récent au sein de chaque groupe de données. Bien que GROUP BY
soit souvent utilisé, cela peut entraîner des problèmes de performances.
Approche sous-optimale
La requête suivante, utilisant une sous-requête et un ordre décroissant, tente ceci :
<code class="language-sql">SELECT * FROM (SELECT * FROM messages ORDER BY id DESC) AS x GROUP BY name</code>
Cette méthode est inefficace car la requête externe analyse la table entière pour chaque groupe, quelles que soient les alternatives plus efficaces.
Solution optimisée (MySQL 8.0)
MySQL 8.0 et versions ultérieures offrent des fonctions de fenêtre pour des opérations améliorées par groupe. ROW_NUMBER()
identifie efficacement le dernier enregistrement de chaque groupe :
<code class="language-sql">WITH ranked_messages AS ( SELECT m.*, ROW_NUMBER() OVER (PARTITION BY name ORDER BY id DESC) AS rn FROM messages AS m ) SELECT * FROM ranked_messages WHERE rn = 1;</code>
Cette requête classe chaque ligne au sein de son groupe, puis sélectionne uniquement le (dernier) enregistrement le mieux classé de chacun.
Alternative (pré-MySQL 8.0)
Pour les anciennes versions de MySQL (avant 8.0), cette approche convient :
<code class="language-sql">SELECT m1.* FROM messages m1 LEFT JOIN messages m2 ON (m1.name = m2.name AND m1.id < m2.id) WHERE m2.id IS NULL;</code>
Cela utilise un LEFT JOIN
pour rechercher des lignes sans id
supérieur au sein du même groupe, isolant ainsi le dernier enregistrement de chacun.
Considérations relatives aux performances
La requête optimale dépend fortement de la taille de vos données, de la distribution des groupes et des index existants. L'analyse comparative de votre scénario spécifique est cruciale pour sélectionner la solution la plus efficace.
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!