1
votes

Requête de table multiple MySQLi

J'ai du mal à déterminer quelles fonctions utiliser pour obtenir ce dont j'ai besoin - répertorier toutes les entreprises par ordre croissant et tous leurs utilisateurs respectifs.

Jusqu'à présent, j'ai créé 2 tableaux: "entreprises" et "utilisateurs" et les a connectés avec une clé étrangère comme ci-dessous:

J'ai essayé de faire des requêtes JOIN pour utiliser les deux tables qui fonctionnaient dans une certaine mesure, cependant Je ne sais pas comment le corriger. Voici ce que je continue de causer: entrez la description de l'image ici

Comme vous pouvez le voir, la société "Contoso" est répertoriée deux fois car elle a 2 utilisateurs qui lui sont associés dans le tableau des utilisateurs. Le code que je fais est:

// Nested Query Test
$nestquery1 = "SELECT companies.name, users.fname, users.lname FROM companies INNER JOIN users ON companies.id = users.cid ORDER BY companies.name ASC";
$nestresult1 = $mysqli->query($nestquery1);

$nestquery2 = "SELECT companies.id, users.fname, users.lname FROM users INNER JOIN companies ON users.cid = companies.id ORDER BY fname ASC";
$nestresult2 = $mysqli->query($nestquery2);

if($nestresult1->num_rows > 0) {
    while($row = $nestresult1->fetch_assoc()){
        $company = $row['name'];
        echo "<div class='customer'>";
        echo "<div class='name'>";
        echo $company;
        echo "</div>";
        if($nestresult2->num_rows > 0) {
            while($row = $nestresult2->fetch_assoc()){
                $fname = $row['fname'];
                $lname = $row['lname'];
                $name = $fname . " " . $lname;
                echo "<div class='contacts'>";
                echo "<li>";
                echo $name;
                echo "</li>";
                echo "</div>";
            }
        }
        echo "</div>";
    }
} else {
    echo "No results";
}

Les divs en font juste un élément de bloc et changent la couleur.

Comment puis-je obtenir tous les utilisateurs dans leur entreprise pertinente plutôt qu'une ligne pour chaque entreprise et utilisateur? J'ai essayé l'imbrication mais j'étais plus éloigné de l'objectif final, voici le code:

$joinquery = "SELECT companies.id, companies.name, users.fname, users.lname FROM users RIGHT JOIN companies ON users.cid = companies.id ORDER BY name ASC";
       $joinresult = $mysqli->query($joinquery);

       if($joinresult->num_rows > 0) {
           while($row = $joinresult->fetch_assoc()){
               $company = $row['name'];
               $fname = $row['fname'];
               $lname = $row['lname'];
               $name = $fname . " " . $lname;
               echo "<div class='customer'>";
               echo "<div class='name'>";
               echo $company;
               echo "</div>";
               echo "<div class='contacts'>";
               echo $name;
               echo "</div>";
               echo "</div>";
           }
       } else {
           echo "No results";
       }

L'aide sera très appréciée!


0 commentaires

3 Réponses :


2
votes

Puisque vous commandez par le nom de l'entreprise, vous devriez être en mesure de vérifier quand le nom de l'entreprise a changé afin de savoir quand créer un nouveau conteneur.

$currentCompany = "";

while($row = $joinresult->fetch_assoc()){
    $company = $row['name'];
    $fname = $row['fname'];
    $lname = $row['lname'];
    $name = $fname . " " . $lname;

    if($currentCompany != $company) {
        if($currentCompany != "")
            echo "</div>";

        $currentCompany = $company;

        echo "<div class='customer'>";
        echo "<div class='name'>";
        echo $company;
        echo "</div>";
    }

    echo "<div class='contacts'>";
    echo $name;
    echo "</div>";
}


1 commentaires

Cela a parfaitement fonctionné, j'ai juste besoin de trier mes trucs divs et css maintenant. Merci beaucoup!!



1
votes

Vous avez deux options, (A) utiliser une jointure ou (B) utiliser deux requêtes comme vous avez tenté de le faire. La jointure vous obligera à suivre la société pour un changement, mais les deux requêtes ne le seront pas. Il y a des avantages et des inconvénients aux deux options qui sont:

  • A) Les jointures comme celle-ci sont rapides, mais vous retournerez les détails de la société pour chaque enregistrement, ce qui entraînera une charge de trafic supplémentaire dans les communications avec la base de données. Cela peut être un problème si le serveur de base de données se trouve sur un serveur séparé ou si vous avez affaire à un énorme ensemble de données. N'oubliez pas que même si les données supplémentaires semblent être une petite quantité, multipliez-les par le nombre de visiteurs simultanés attendus sur le site Web et vous pourriez saturer le lien de votre base de données.

    L'exemple fourni par @ abney317 est précis, mais au lieu de comparer le nom de l'entreprise, je comparerais le cid car non seulement il sera plus performant, mais il sera plus fiable.

  • B) C'est la méthode que j'opterais, bien qu'elle soit un peu plus complexe à implémenter et nécessite deux requêtes au lieu d'une, c'est l'option la plus évolutive et maintenable dans le futur. Cela rendra également votre code un peu plus facile à suivre et à déboguer.

    Exemple:

    // Nested Query Test
    $rsCompanies = $mysqli->query("SELECT cid, name FROM companies ORDER BY name");
    while($company = $rsCompanies->fetch_assoc())
    {
      echo "<div class='customer'>";
      echo "<div class='name'>" . htmlspecialchars($company['name']) . "</div>";
      echo "<div class='contacts'>";
      echo "<ul>";
      $rsUsers = $mysqli->query("SELECT fname, lname FROM users WHERE cid = " . $company['id']);
      while($user = $rsUsers->fetch_assoc())
      {
        $name = htmlspecialchars($user['fname'] . " " . $user['lname']);
        echo "<li>$name</li>";
      }
      echo "</ul>";
      echo "</div>";
      echo "</div>";
    }
    

Quelques remarques supplémentaires:

  • Utilisez toujours htmlspecialchars lors de la sortie de texte d'une base de données qui ne doit pas contenir de HTML, faute de quoi vous ouvrirez les vecteurs d'attaque XSS.

  • Je n'ai pas échappé SQL à l'ID de l'entreprise, car selon le schéma de votre base de données, il s'agit d'un entier et comme il n'est pas fourni par l'utilisateur final, il est sûr de l'utiliser directement, évitant ainsi toute surcharge de traitement supplémentaire. p>


1 commentaires

Je n'ai jamais pensé à utiliser la fonction where pour utiliser la variable comme ça. Cela rend maintenant la croissance et les modifications tellement plus faciles. Peut désactiver et activer les utilisateurs avec un booléen maintenant: $ rsUsers = $ mysqli-> query ("SELECT fname, lname FROM users WHERE (cid =". $ Company ['id']. ") AND (enabled! = 'True ') ");



-1
votes

Si vous n'avez besoin d'afficher que quelques champs, essayez de récupérer les données en une seule requête: violon sql

SELECT c.name company_name,
group_concat(u.name) employees_name
FROM companies c JOIN users u on c.id = u.cid
group by c.name;


0 commentaires