Requête, boucle et jointure - Version imprimable +- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org) +-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38) +--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51) +--- Sujet : Requête, boucle et jointure (/showthread.php?tid=2255) Pages :
1
2
|
Requête, boucle et jointure - phenix - 07-01-2008 Bonjour à tous, Cela fait un moment que sa me turlipine, et soucieux d'optimise un peu mon site (enfin c'est surtout en regardant les graphique d'utilisation du serveur ) j'ai un peu regarder les topic de jeuPHP et je me suis renseigner. J'ai vut qu'il était largement déconseiller de faire des requêtes dans des boucles (au final c'est largement conpréhensible :mauvais. Et horreur pour moi, j'en fait beaucoup trop. Seulement je n'arrive pas a trouver un moyen de les enlever des boucles, je m'adresse donc a vous. j'ai 2 tables: monstre et users. La première contient toute les donnée des monstres (niveau, caractéristique, etc...) et la seconde, toute les données des joueurs (Dur :good. Voici leurs structures: Users: Code : CREATE TABLE `users` ( Monstre: Code : CREATE TABLE `monstre` ( Pour afficher les monstre et les joueurs sur la map, je récupère les positions: Code PHP :
Problème: je doit faire une requête suplémantaire dans ma boucle pour récupérer le reste des informations du joueur/monstre: Code PHP :
Comment pourrai-je faire pour envoier directement les info dans la fonction Sans devoir faire de requête (et bien sur en séléctionnant les bonne information ) ? Merci d'avance de votre aide éclairé :wowowow: Phenix RE: Requête, boucle et jointure - Sephi-Chan - 07-01-2008 Il faudrait que tu nous montre ce à quoi ressemble la table état. Je suppose que tu veux avoir une relation de type 0, n, c'est à dire un monstre peut avoir zéro ou plusieurs états (empoisonnés, paralysée, etc.). Ça nous permettra de t'indiquer comment les sortir de ta boucle. Il faudrait aussi savoir comment fonctionne ta table listemonstre. En attendant, un petit commentaire : Utilise plutôt des identifiants numériques, plus rapides : le traitement de clés FULLTEXT est bien plus lent (et plus lourd en base). Par exemple, dans la colonne bouclier, je suppose que tu indiques le nom du bouclier dont les statistiques sont stockées dans une table objets. Si ce n'est pas le cas, je te conseille de le faire et de faire références aux objets par leur identifiant. Car tu imagines si tu dois écrire "Égide du Dieu sanglant" dans la case bouclier de chaque monstre, ça fait une table très lourde !? Sephi-Chan RE: Requête, boucle et jointure - phenix - 07-01-2008 Citation :Il faudrait que tu nous montre ce à quoi ressemble la table état. Je suppose que tu veux avoir une relation de type 0, n, c'est à dire un monstre peut avoir zéro ou plusieurs états (empoisonnés, paralysée, etc.). Ça nous permettra de t'indiquer comment les sortir de ta boucle. Voila Code : CREATE TABLE `etat` ( Citation :Il faudrait aussi savoir comment fonctionne ta table listemonstre. Cette table contient les profile de base des monstres, cela me permet d'automatiser leur création et de faire des comparaisons avec leur PV de base. Voici sa structure: Code : CREATE TABLE `listemonstre` ( Citation :Par exemple, dans la colonne bouclier, je suppose que tu indiques le nom du bouclier dont les statistiques sont stockées dans une table objets. Si ce n'est pas le cas, je te conseille de le faire et de faire références aux objets par leur identifiant. Car tu imagines si tu dois écrire "Égide du Dieu sanglant" dans la case bouclier de chaque monstre, ça fait une table très lourde !? Certes, mais lorsque je veux afficher le nom du bouclier, je dois faire une requête SQL en plus pour récupérer le nom de l'objet :heuuu:. Mon "système d'inventaire ce décline en 3 tables: Objet, qui contient les caractéristique de chaque objet. Inventaire, qui contient le pseudo des joueur et le nom de l'objet dans l'inventaire et enfin la table users qui contient dans les champs arme,armure,etc. le nom des objet équipé. Je pourrais transformé tout sa en identifiant numérique (les ID de la table objet) mais alors, cela voudrais dire que pour afficher les noms des objets je doit faire un requête sur celle-ci. En stockant le nom, je peux l'afficher directement. :heuuu: A moins que je me trompe ? Merci de votre aide, Phenix RE: Requête, boucle et jointure - Anthor - 07-01-2008 Citation :Certes, mais lorsque je veux afficher le nom du bouclier, je dois faire une requête SQL en plus pour récupérer le nom de l'objet 6. Non, c'est la que tu utilise les jointures, par exemple : Code : SELECT user.id, bouclier.nom AS bouclier_nom A adapter en fonction des tables que tu as evidemment ^^ RE: Requête, boucle et jointure - Sephi-Chan - 07-01-2008 Voilà ce que je te propose comme structure pour la table état (et la manière de découper les tables s'applique dans de nombreux cas) : Table Etats, qui contient les bonus, malus sur les différentes caractéristiques (celles données sont là à titre d'exemple ) :
Ensuite, ta table Monstres. Alors là, si tu veux que chaque monstre soit identique (d'un point de vue caractéristiques et compétences), tu peux créer des gabarits de monstres et les instancier dans une autre table. Mais à la limite on pourra voir ça plus tard, pour ne pas tout compliquer d'un coup.
Ensuite, on aura une table Monstre_a_Etat lie un monstre à une altération d'état :
Si tu veux utiliser les mêmes altérations d'état pour les joueurs, il faut que tu crées une table de relation Joueur_a_Etat sur le même modèle. Petite note à propos des types de champs numériques :
Ensuite, grâce aux jointures, tout devient plus simple (et c'est pas marketting !). (J'édite au fur et à mesure, sauf si l'explication de Anthor t'as suffit. ) Sephi-Chan RE: Requête, boucle et jointure - phenix - 07-01-2008 Citation :Si les joueurs ont les mêmes caractéristiques que les monstres, cette table peut servir à décrire des altérations d'état pour les deux. oui, les joueur et les monstres on les même caractéristique, en fait un monstre c'est un joueur (sauf pour le calcule des PV). Citation :Ensuite, ta table Monstres. Alors là, si tu veux que chaque monstre soit identique (d'un point de vue caractéristiques et compétences), tu peux créer des gabarits de monstres et les instancier dans une autre table. Mais à la limite on pourra voir ça plus tard, pour ne pas tout compliquer d'un coup. 2 Je n'avait jamais penser a stocker tout simplement le nombre de PV_max :respect:. C'est vrai que rien qu'avec sa, on économise une requête :good: Les "gabarit" existe déjà, c'est la table liste monstre, par contre je ne sais pas ce que veux dire instancier :heuuu:. Les monstres sont crée pour le moment en 2 requêtes: Une qui choisi au hasard un monstre sur la table listemonstre (avec ORDER BY rand()) et une autre qui fait un INSERT dans la table monstre. Par contre un truc que je comprend pas. Le nombre d'état que peu subir un joueur/monstre est illimité (enfin en théorie, en pratique c'est différent) dès lors tu utilise: Id : TINYINT (UNSIGNED) et puis tu me dis: Citation :La valeur d'un TINYINT vaut entre -127 et 127. Et vaut entre 0 et 255 si on lui donne l'attribut UNSIGNED. Cela ne va t'il pas limité le nombre d'état possible dans la table ? (mes champ id sont en auto_increment clé primaire) Citation :Ensuite, grâce aux jointures, tout devient plus simple (et c'est pas marketting !). C'est la que j'ai le plus de mal, je me rend bien compte que a quel point les jointures doivent économisé des ressources, seulement j'ai beau lire la doc, et les tuto, quand je veux appliqué le principe sur 2 tables ben sa marche jamais comme prévu :pleure2:. Code : SELECT user.id, bouclier.nom AS bouclier_nom Bon je vais détaillé ce que je sais et ce que je sais pas. Code : SELECT user.id, La on séléctionne l'ID de la table user Code : , bouclier.nom AS bouclier_nom Si je me souviens bien AS sert a "renommer" le champs. Quel est l'intérêt d'un telle pratique ? :heuuu: Code : FROM users AS user Même question, pourquoi renommé la table ? Code : INNER JOIN boucliers AS bouclier j'ai pas de table boucliers mais une table objet m'enfin, je suppose qu'il faudrais juste renommer ? Phenix RE: Requête, boucle et jointure - Anthor - 07-01-2008 phenix a écrit : Ca t'evite de te tromper avec un autre champs qui pourrait s'appeler nom, de cette façon, tu peux séparer user.nom et bouclier.nom phenix a écrit :Ca me permet de séparer la table users qui contient tous les utilisateurs et user qui est la ligne de l'utilisateur que je sélectionne phenix a écrit : Exactement, tu peux l'appliquer sur n'importes quelles tables en relations. Le nombre de jointure n'est pas limité. RE: Requête, boucle et jointure - phenix - 07-01-2008 Ben alors, il faut que l'on m'explique pourquoi ce code: Code PHP :
Ne renvoie pas la même chose que: Code PHP :
Amicalement, Phenix RE: Requête, boucle et jointure - Sephi-Chan - 07-01-2008 Je vais faire un exemple de jointure pour les altérations, le principe peut être appliqué à plein de choses après. Le tout, c'est d'avoir une structure en 3 tables (ou plus, parfois). Je te conseille par contre, dans tes noms de champs, de rappeler la table. Par exemple dans la table Monstres, tu appelle l'id id_monstre, ça te permet d'éviter de devoir aliaser chaque champ ! Remplissons les tables : Etat (id_etat, nom_etat) (on les effets ne nous intéressent pas pour le moment), qui contient la liste des différents altérations d'état possibles. Je doute qu'il y en ai plus que 255. Citation :1, Stupidité Ensuite, remplissons, la table listeMonstre (id_monstre, nom_monstre, pv_max), qui instancie les modèles de monstres : Citation :1, Chevalier de sang, 60000 Imaginons pendant le jeu qu'un personnage jette un sortilège qui paralyse sa cible sur un Chocobo noir. Alors tu créeras dans la table Monstre_a_Etat (id_monstre, id_etat, duree_effet) une relation : 3 (l'id du monstre (id_monstre de la table Monstres) affecté), 3 (l'id de l'altération d'état (id_etat de la table Etats) qui affecte le monstre), 5 (le nombre de tours de combat durant laquelle l'altération fait effet. Tu le réduit de 1 à chaque tour, quand il atteint 0). Ainsi, il devient possible d'affecter plusieurs altérations d'état à un même monstre ! Imaginons donc qu'un joueur rende malade ce même Chocobo noir, le pauvre ! Alors là, rebelotte, on insère une nouvelle entrée dans la table Monstre_a_Etat : 3 (l'id du monstre Chocobo noir), 4 (l'id de l'altération Maladie), 2 (la durée de l'effet) En pratique, quand tu vas résoudre ton combat, pour récupérer les informations sur les caractéristiques et les altérations d'état du monstre, tu feras un script comme ça : Code : SELECT M.*, E.*, ME.duree_effet J'explique ma requête, on sélectionne toutes les informations de la table Monstres, on va chercher dans la table de relation Monstre_a_Etat si l'id du monstre s'y trouve (le LEFT devant le JOIN sert à sélectionner quand même les informations du monstres s'il n'a aucune altération, mais c'est un détail), si oui, alors on va chercher dans la table Etats ceux qui ont l'id de (ou des) altérations trouvées précédemment dans la table Monstre_a_Etat. Comme tu le vois, on utilise à chaque fois l'id du monstre actuellement parcouru par SQL quand il parcourt les tables à l'exécution de la requête. On spécifie en l'occurrence la bête d'id 3 à la fin, mais si on ne met pas de WHERE, ça sort toutes les bêtes et leurs altérations d'état ! Ça nous sort une ressource genre (je n'écris pas tous les champs dans mon exemple car ce serait trop long pour moi de les lister) : Citation :id_monstre, nom_monstre, …, id_maladie, nom_maladie, …, duree_effet Ce résultat est un peu particulier à exploiter vu qu'il y a des doublons, mais c'est en fait très facile à faire avec PHP (on pourra t'expliquer au besoin). Voilà, j'espère que ça t'aura aidé à comprendre le fonctionnement ! Sephi-Chan RE: Requête, boucle et jointure - phenix - 08-01-2008 Merci Sephi, je commence a comprendre comment cela fonctionne . Déjà j'ai réussi a faire fonctionné ma première jointure, c'étais des erreurs dans la base de donnée :mauvais: Sinon, au lieu d'avoir 2 tables pour les etats, ce ne serais pas plus facile de n'en avoir qu'une seul et de donner de très grand ID au monstre (ici j'ai mit 20000) ? |