Suppression propre d'un membre et tout ce qui le concerne!

WRInaute accro
Bonsoir

Lorsqu'un membre supprime son compte ou que je supprime moi même un membre, je souhaites supprimer ses commentaires et tout ce qui le concerne, malheureusement j'ai un problème (vous vous en doutez :mrgreen: ) .

Lorsqu'un membre commente j'incrémente un champ nb_commentaires dans la table de l'article en question
Mais comment supprimer un membre et mettre a jour nb_commentaires de tous les articles qui ont perdu des commentaires de ce membre et ceci sans faire sauter le serveur avec des tonnes de update dans une boucle? (imaginons le cas de figure d'un membre qui a posté plusieurs dizaines voir centaines de commentaires sur différents articles)

Pour mieux visualiser le problème voici mes tables :

Code:
Ma table  : t_articles
id_article
titre
contenu
nb_commentaires
....


Ma table : t_commentaires
id_commentaire
id_membre
....


Ma table : t_membres
id_membre
pseudo
password
....

J'aimerais donc pouvoir décrémenter tous les nb_commentaires de chaque articles concernés par ce membre supprimé. Comment faire sans faire des tonnes d'Update?

Existe t-il d'autres solutions pour conserver le nombre de commentaires pour chaque article et qu'il se mette à jour de façon automatique évitant ainsi ce problème?

Solution possible mais peu précise, c'est que je mette à jour le nb_commentaires lorsqu'un membre (pas celui qui a été supprimé bien sur) vient poster un commentaire. Le problème c'est que tant que personne ne vient poster un commentaire la valeur de nb_commentaires sera faussée.

Petite précisions qui me semble un poil inutile, si j’utilise "nb_commentaires" c'est pour éviter de faire un "select count" a chaque fois que j'ai besoin d'indiquer le nombre de commentaires pour un article.
 
WRInaute accro
C'est quoi la liaison entre t_articles et t_commentaires ?
Il en faut une pour lier l'article et ses commentaires. De plus sans cela on ne peut pas répondre a ta question. :wink:

Sinon dans le principe tu peux mettre a jours le Nb de commentaires pour tous les articles après le del en faisant un update global, synchro avec un count de com groupé sur justement ce qui manque savoir un id d'article dans la table commentaire.

A l’arrache sans tester ni réfléchir trop (il est tard) :
update
t_articles as A,
t_commentaires as B
set
A.nb_commentaires = count(B.id_commentaire)
where
A.id_article = B.id_article
group by B.id_article
 
WRInaute accro
Effectivement j'ai oublié d'indiquer dans mon post précedent le id_article dans t_commentaires. Il est effectivement bien présent ;)

t_commentaires ressemble bien à ceci :
id_commentaire
id_membre
id_article
etc.

Dans la solution que tu proposes tu met à jour l'ensemble des articles, même si ce n'est qu'avec un seul Update, j'imagine que si j'ai plus de 10 000 articles, ca risque de faire sacrément remuer la BDD ;)

J’imagine qu'il faudrait l'améliorer avec ceci :

update
t_articles as A,
t_commentaires as B,
t_membres as C
set
A.nb_commentaires = count(B.id_commentaire)
where
A.id_article = B.id_article
and
B.id_membre=C.id_membre
group by B.id_article

Requête qui devrait donc se faire avant le delete du membre

N'hésites pas à me dire si je fais fausse route :)
Par contre j'ai beaucoup de mal avec les group by (ou les having) que je ne maitrise pas, et ici dans cette requête je n'arrive pas à saisir son éventuel intérêt. Mais comme tu l'a dit il se fait tard et il faudrait que je regarde ça à tête reposée :wink:
 
WRInaute accro
ca risque de faire sacrément remuer la BDD
Possible faut tester mais bon tu peux faire ça une fois par 24 heurs avec un cron de nuit quand c'est calme ... surtout que c'est pas de la data vitale.
Après le souci c'est que ce genre de data si tu gère un cache d'output ne changera rien a l'affichage si le cache est pas mis a jour mais c'est un autre souci.

B.id_membre=C.id_membre
Bah faire un update avant le delete reviens a rien faire si je ne me trompe car je suppose que tu vas delete ses messages aussi pour qu'ils ne soit plus comptés. Donc que le membre soit présent dans la table user ou pas ne changera rien au count et si ses messages ne sont plus là dan s la table commentaire et bien ça marchera pas puisque tu sélectionnera rien.

En dernier lieu faut une procédure stockée je pense. Mais là :?

Le group by il est destiné a grouper des commentaires par "qque chose" si tu groupe par article, alors le count reflètera le nombre de messages de cet article précis.

J'ai une table qui a un peut la même structure que la tienne si je fais :

SELECT count(photo), pseudo FROM `apport` group by pseudo order by count(photo) desc

j'obtiens la liste des participant (par pseudo) avec le nombre de photos qu'ils ont partagé (accessoirement c'est triè le plus gros au plus petit)

la structure est du style :
`apport` [ `id`, `photo`, `description`, `pseudo`]

edit > quoi qu'il en soit pense a optimiser les tables impactées après les delete ...
 
WRInaute accro
je te remercies, je vais étudier ça :wink:

Je vous tiens au courant :mrgreen:

PS : j'ai l'impression que UPDATE ne supporte pas le group BY en tout cas avec Mysql
 
WRInaute accro
Alors après quelques recherches et essais peu concluants j'ai fini par trouver ceci avec une requête imbriquée :

UPDATE t_articles AS B,
(SELECT C.id_article, count(C.id_commentaire) AS nbcoms
FROM t_commentaires AS C, t_articles AS TB
WHERE TB.id_article=C.id_article GROUP BY C.id_article)
AS S
SET B.nb_commentaires = S.nbcoms
WHERE B.id_article=S.id_article
AND B.nb_commentaires!=s.nbcoms;

la partie en verte semble légèrement réduire le traitement de la requete : je passe de 0,025 voir 0,030 sec à 0.0180
sachant que sur ma table de test j'ai 2 000 articles et plus de 3 500 commentaires et seulement 650 commentaires ont eu des commentaires.

Difficile de savoir si cette requête est donc trop gourmande ou non, qu'en pensez vous? Un peu peur que ce temps de traitement augmente sérieusement si j'ai plus de 10 000 articles et si le nombre de commentaires est multiplié par 10 voir plus.

Le résultat me semble donc plutôt convainquant actuellement mais sur du long terme... (pas fan en général des requêtes imbriquées). Après c'est le genre de requête qui sera effectuée uniquement en cas de suppression d'un membre (ce qui n'arrive pas toutes les 10 minutes non plus normalement)

l'idéal serait quand même de mettre à jour uniquement les articles concernés par la suppression du membre, ce qui réduirait considérablement le temps de traitement de la requête. Peut être en passant par des tables temporaires (mais je ne maitrise absolument pas)

D'ailleurs petite question en passant ;)
Lorsqu'un membre est supprimé de WRI, tous ses posts sont-ils supprimés?


PS : je confirme cette requête va vite péter un plomb. J'ai fait le test j'ai intégré plus de 50 000 commentaires. Je suis passé à 0,60 sec de temps de traitement. Ce qui me semble énorme, et c'est toujours basé sur à peine 2000 articles.
 
WRInaute accro
Bon

Voilà une solution qui semble moins gourmande et qui prend en compte le membre pour le Update :

UPDATE t_articles AS B,
(SELECT C.id_bloc, count(C.id_commentaire) AS nbcoms FROM t_commentaires AS C, t_articles AS TB, t_membres AS M WHERE TB.id_article=C.id_article AND M.id_membre=C.id_membre AND M.id_membre=XXX GROUP BY C.id_article) AS S
SET
B.nb_commentaires = B.nb_commentaires - s.nbcoms
WHERE B.id_article=S.id_article
AND
B.nb_commentaires>=s.nbcoms

Après cette requête je supprime les commentaires du membre dans t_commentaires
et ensuite le membre.

En vert c'est pour à un éventuel bug : si jamais nb_commentaires est inférieur a nbcoms sinon aurait un résultat aberrant.

Donc avec cette requête il semblerait qu'on limite de façon importante le temps de traitement lorsqu'un supprime un membre. A moins que le membre est posté des dizaines de milliers de commentaires ça devrait aller très vite.

Dites moi ce que vous pensez de cette solution :)
 
Discussions similaires
Haut