Lors de l'utilisation de la fonction de groupe pour filtrer l'ensemble de résultats, quelques problèmes rencontrés et solutions [Recommandé : Tutoriel vidéo mysql]
1.
Il y a deux tablesTable d'articles (table de messages un à plusieurs)t_posts : oid, posts_name
Table de messages (table d'articles plusieurs à un)
t_comment : oid, posts_id, msg_content, create_time
2. Analyse des exigences
Requête du dernier contenu de réponse de chaque article3.Écriture SQL
select tp.oid, tp.posts_name, tc.msg_content, tc.create_time from t_posts tp left join t_comment tc on tp.oid = tc.posts_id group by tp.oid having create_time = max(create_time)
Supposons qu'il y ait deux articles A et B (l'ordre des enregistrements de réponse dans la base de données est cohérent avec ce qui suit)
<p>A有一个回复记录时间为: 2019-09-10 <br>A有一个回复记录时间为: 2019-09-11 <br>B有一个回复记录时间为: 2019-09-01 <br>B有一个回复记录时间为: 2019-09-09<br></p>Lorsque vous exécutez le SQL ci-dessus, vous constaterez qu'un grand nombre d'enregistrements sont perdus dans l'ensemble de résultats et que les résultats sont faux. Après avoir interrogé les données, nous savons que mysql a. est exécuté après group by, c'est-à-dire en regroupant d'abord, puis en filtrant, mais comme il y a plus de deux enregistrements de message,
donc le résultat défini après le regroupement ne prendra que le premier message de chaque message comme information d'enregistrement après le regroupement. cette fois, si vous utilisez create_time = max(create_time)
alors, max (create_time) est la durée maximale du regroupement actuel
Donc le sql ci-dessus perdra l'ensemble de résultats
4. Transformez le SQL
car il sait que le regroupement sera fusionné L'ensemble de résultats répété est celui avec le plus petit numéro de ligne, pouvons-nous donc modifier le SQL comme suit ??select tp.oid, tp.posts_name, tc.msg_content, tc.create_time from t_posts tp left join t_comment tc on tp.oid = tc.posts_id group by tp.oid having create_time = max(create_time) -- 下面的是新增的sql order by tc.create_time descAprès l'avoir exécuté, j'ai découvert que cela ne fonctionnait toujours pas, ce qui prouve que order by est après group by & have
Plus tard, j'y ai réfléchi, puis-je ne pas l'avoir ? Que diriez-vous d'utiliser directement order by pour optimiser le ? résultats groupés ?
ayant create_time = max(create_time)
select tp.oid, tp.posts_name, tc.msg_content, tc.create_time from t_posts tp left join t_comment tc on tp.oid = tc.posts_id group by tp.oid order by tc.create_time descL'erreur d'ensemble de résultats n'affecte pas les résultats de regroupement. Les ensembles de résultats en double sont toujours fusionnés en fonction du regroupement minimum de rownum, puis dans le tri
. 5. La version modifiée ultime
Parce que l'ordre par ne peut affecter que le groupe par, est-il possible de trier le résultat défini avant le groupe par, puis de le regrouper ?select * from ( select tp.oid, tp.posts_name, tc.msg_content, tc.create_time from t_posts tp left join t_comment tc on tp.oid = tc.posts_id order by tc.create_time desc ) t group by t.oidJ'ai trouvé que ce n'est toujours pas facile à utiliser, mais la sous-requête est en effet triée en premierAprès l'interrogation (expliquer), il s'avère que l'ordre par de la sous-requête a été optimisé Solution :
- Utilisez la limite 99999 dans la sous-requête
- Utilisez la condition Where dans la sous-requête, create_time. = (sélectionnez max (create_time) dans le groupe t_comment par oid)
-
select * from ( select tp.oid, tp.posts_name, tc.msg_content, tc.create_time from t_posts tp left join t_comment tc on tp.oid = tc.posts_id order by tc.create_time desc limit 9999 ) t group by t.oid
Terminé
Points de connaissances supplémentaires :Différence entre les versions mysql5.5 et mysql 5.7 : version 5.7+, si la limite n'est pas utilisée, regrouper par optimisera la commande d'ici