1
votes

SQL / PHP: jointures sans correspondance sur l'autre table (plusieurs tables)

J'ai quatre tableaux:

    <?php 
            //code to search for a item from the database
            // user can enter any character to search for a value from the db
           if (isset($_POST['search']))
           {
               $valueToSearch = $_POST['ValueToSearch'];
               $query = "select * from client WHERE concat(`clientID`, `name`, `age`, `sex`, `weight`, `height`, `yearsExperience`, `goal`, `injuries`, 'email')like'%".$valueToSearch."%'";
               $search_result = filterTable($query);

           }
           else {
           $query = "select *
            from client
            where clientID in (select clientID from nutrition_plan where personaltrainerID=?)
            or clientID in (select clientID from training_plan where personalTrainerID=?)";
           $query->bind_param("i", $_POST[""]);
               $search_result = filterTable($query);
           }
           //code to filter the db
           function filterTable($query)
           {
               $connect = mysqli_connect("localhost:3308","root","","fypdatabase");
               $filter_Result = mysqli_query($connect, $query);
               return $filter_Result;
           }
           ?>

           <?php
           while($row = mysqli_fetch_array($search_result))
          { //display the details from the db in the table with option to delete or update entry 
            ?>
                    <tr>
                    <td><?php echo $row["clientID"]; ?></td>
                    <td><?php echo $row["name"]; ?></td>
                    <td><?php echo $row["age"]; ?></td>
                    <td><?php echo $row["sex"]; ?></td>
                    <td><?php echo $row["weight"]; ?></td>
                    <td><?php echo $row["height"]; ?></td>
                    <td><?php echo $row["yearsExperience"]; ?></td>
                    <td><?php echo $row["goal"]; ?></td>
                    <td><?php echo $row["injuries"]; ?></td>
                    <td><?php echo $row["email"]; ?></td>
                    <td> 
                        <a href="?Delete=<?php echo $row["clientID"]; ?>" onclick="return confirm('Are you sure?');">Delete</a>
                    </td>
                    <td>
                        <a href="updateClient.php?Edit=<?php echo $row["clientID"]; ?>" onclick="return confirm('Are you sure?');">Update</a>
                    </td>
                  </tr>
                  <?php

J'essaie d'afficher que lorsqu'un entraîneur personnel crée un plan de nutrition / d'entraînement et l'attribue à un client, seuls leurs clients spécifiques apparaissent comme résultat, mais il n'y a pas de clé étrangère dans la table client pour identifier le coach (en raison des critères du projet)

Je me demande quel est le SQL pour la jointure nécessaire à la fois sur l'entraînement / la nutrition plan. J'essaie depuis un certain temps et voici mon exemple de code.

Le résultat souhaité est toutes les données du client SI UNIQUEMENT ils ont reçu un plan d'entraînement ou de nutrition par ce formateur spécifique

Dans la déclaration, j'ai des problèmes avec le paramètre Bind afin que seuls les utilisateurs avec des clients puissent voir leurs clients. Si j'utilise un identifiant spécifié, je peux obtenir un retour!

Personal_trainer(personaltrainerID, name, age, location)
Client(clientID, name, age, location)
Nutrition_Plan(NutritionplanID, personaltrainerID, clientID)
Training_Plan(TrainingplanID, personaltrainerID, clientID)


10 commentaires

«SI SEULEMENT ils ont reçu un plan de formation / nutrition» ET ou OU?


Vous voudrez peut-être une simple chaîne INNER JOIN avec la clause USING (xxxID) . dev.mysql.com/doc/refman/8.0/en/join. html


OU! désolé mal faire le changement!


vous avez une erreur dans votre requête SELECT * FROM puis LEFT JOIN avec tous les critères et après filtrage en utilisant WHERE


@ Quasimodo'sclone merci! comment écrire ça?


Ensuite, vous avez besoin d'un DISTINCT personaltrainerID, clientID dans une requête UNION . dev.mysql.com/doc/refman/8.0/en/union. html


Jusqu'à présent, cette requête est presque là. J'ai juste besoin de changer ce que le "id" est égal à la fin: '"SELECT * from client JOIN nutrition_plan ON client.clientID = nutrition_plan.clientID JOIN personal_trainer ON personal_trainer.personalTrainerID = nutrition_plan.personaltr‌ AinerID Où personal_trainer.personalTrainerID = 'id' "; '


Si vous avez jusqu'à présent une solution fonctionnelle et que vous avez des questions supplémentaires telles que les paramètres de liaison de votre formulaire HTML, vous devez accepter une réponse et ouvrir une nouvelle question spécifique avec l'extrait de code HTML et PHP. StackOverflow (SO) est destiné à répondre à un problème spécifique par question.


Super, je vais ouvrir une nouvelle question, merci beaucoup pour votre aide, tout ce que je dois faire est de corriger le paramètre de liaison !! Merci beaucoup :)


Super, je vais ouvrir une nouvelle question, merci beaucoup pour votre aide, tout ce que je dois faire est de corriger le paramètre de liaison !! Merci beaucoup :)


3 Réponses :


0
votes

Cela devrait fonctionner

SELECT * from client JOIN nutrition_plan ON client.clientid = nutritionplan.clientid JOIN Personaltrainer ON Personaltrainer.personaltrainerID = nutritionplan.personaltrainerID Où Personaltrainer.personaltrainerID = "id"


4 commentaires

Merci Kashan, c'est presque là! Mais quel est le "id" à la fin aussi? thats où mon erreur est, personaltrainerID?


cela devrait en fait afficher cela via son identifiant ou son nom personnel


Je vous comprends, il ne lance aucune erreur et s'exécute, mais aucune donnée n'est affichée dans le tableau!


@ Darán: Cette requête vous donne un entraîneur personnel, ses plans de nutrition et les clients associés. Si vous prenez la requête telle quelle, c'est-à-dire avec "id" littéralement, vous recherchez l'ID du formateur 0, car "id" signifie une colonne nommée id < / code>, et comme cela n'existe pas, MySQL utilise par défaut une chaîne 'id' , et comme ce n'est pas un nombre, il est converti en 0 .



1
votes

Voyons si je comprends bien votre demande ...

N'afficher que les clients qui ont un plan de nutrition ou d'entraînement par le formateur 123:

select *
from client
join
(
  select 'nutrition' as kind, nutritionplanid as id, personaltrainerid, clientid
  from nutrition_plan
  union all
  select 'training' as kind, trainingplanid as id, personaltrainerid, clientid
  from training_plan
) plan using (clientid)
where clientid in (select clientid from nutrition_plan where personaltrainerid = 123)
   or clientid in (select clientid from training_plan where personaltrainerid = 123);

Montrez ces clients avec avec tous leurs plans (quels que soient les formateurs des plans):

select *
from client
where clientid in (select clientid from nutrition_plan where personaltrainerid = 123)
   or clientid in (select clientid from training_plan where personaltrainerid = 123);


9 commentaires

Cela a l'air bien merci! quand le pesonaltrainerID provient de la base de données et pourrait être n'importe quel nombre, quel serait-il au lieu de «123» par exemple? Serait-ce '?'


Cela vient de la base de données? Qu'est-ce que ça veut dire? À partir d'une autre table, par ex. sélectionnez personaltrainerid dans personal_trainer où name = 'John Smith' ? Ensuite, vous pouvez simplement remplacer 123 par cette sous-requête entre parantheses: ... where personaltrainerid = (select personaltrainerid from personal_trainer where name = 'John Smith'));


Super merci! donc je devrais prendre votre deuxième exemple qui devrait fonctionner?


Si c'est ce que tu veux. Essayez-le et vérifiez les résultats. La requête vous permet d'obtenir tous les clients avec tous leurs plans, à condition qu'au moins l'un des plans du client soit par le formateur souhaité.


Je vous remercie, j'ai essayé la première requête et aucune erreur n'était présente mais la sortie du client n'était pas affichée dans le tableau!


Assurez-vous d'utiliser l'ID de formateur d'un formateur qui a effectivement un plan dans nutrition_plan ou training_plan.


Cela a fonctionné pour cet ID spécifique! Cependant, je veux faire en sorte que tout formateur de la table voie ses propres clients lorsqu'il se connecte avec son identifiant? par exemple, les identifiants 4, 6, 8 ne verraient que leurs clients, devrais-je utiliser «?» pour ça? Un autre mot, tout personalTrainerId dans les plans de formation / nutrition


Oui, mysqli utilise le ? pour les paramètres de liaison. Voici les documents associés: php.net/manual/de/mysqli. quickstart.prepared-statements.php


J'ai mis à jour la question ci-dessus avec le paramètre bind mais je ne sais pas quoi écrire après le "i" pour un entier?



1
votes
SELECT name, age, location FROM Client
INNER JOIN
(
  SELECT personaltrainerID, clientID from Nutrion_Plan 
  UNION DISTINCT 
  SELECT personaltrainerID, clientID from Training_Plan
) u
USING(clientID)
WHERE u.personaltrainerID = ?;

8 commentaires

Merci c'est super !! Que remplaceriez-vous "1" au lieu de pour que différents PersonaltrainerID puissent être utilisés lorsque différents formateurs se connectent?


Bien sûr, un paramètre comme ? pour une instruction préparée.


Quand j'inclus un? marquer seul aucun résultat n'est renvoyé, devrait-il y avoir une autre ligne pour lier un paramètre? Voir mon exemple édité ci-dessus s'il vous plaît!


Puisque vous avez marqué votre question comme appartenant à PHP, je suppose que vous souhaiterez utiliser la méthode prepare de mysqli ou de DBO. php.net/manual/en/mysqli.quickstart.prepared-statements. php / php.net/manual/en/pdo.prepared- statement.php C'est fortement recommandé car l'interpolation des données client directement dans SQL rendrait votre application vulnérable aux attaques par injection SQL.


J'utilise le paramètre de liaison mais après le "i" pour un entier, je ne sais pas quelle valeur y passer? $ query-> bind_param ("i", $ _POST [""]); ----> je ne sais pas ce qui est censé être là où se trouve la publication


@ Darán Vous pouvez également utiliser un paramètre nommé comme : trainerid .


C'est quelle que soit votre forme . Il est reflété dans le tableau $ _POST , à condition que la méthode de formulaire soit post, sinon $ _GET .


Il n'est probablement pas posté via le formulaire mais extrait de $ _SESSION s'il y a une connexion de formateur. Sinon, il peut y avoir un champ déroulant affichant les noms sous forme de légendes et envoyant l'ID sélectionné. Ensuite, vous pourriez trouver une balise