MySQLi Многостоловый запрос - PullRequest
0 голосов
/ 02 января 2019

Борьба с выяснением, какие функции использовать, чтобы получить то, что мне нужно - перечислить все компании в порядке возрастания и всех их соответствующих пользователей.

До сих пор я создал 2 таблицы: «компании» и «пользователи» и связал их с внешним ключом, как показано ниже:

Я пытался выполнить запросы JOIN для использования обеих таблиц, которые работали до некоторой степени, хотя я не могу понять, как это исправить. Вот что я продолжаю вызывать: enter image description here

Как видите, компания "Contoso" указана дважды, так как в таблице пользователей с ней связано 2 пользователя. Код, который я делаю:

$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";
       }

Дивы просто делают его блок-элементом и меняют цвет.

Как получить всех пользователей в соответствующей компании, а не ряд для каждой компании и пользователя? Я пытался вложить, но я был дальше от конечной цели, ниже приведен код:

// 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";
}

Помощь будет очень ценится!

Ответы [ 3 ]

0 голосов
/ 02 января 2019

У вас есть два варианта: (A) использовать объединение или (B) использовать два запроса, как вы пытались это сделать.Объединение потребует от вас отслеживать изменения компании, однако два запроса не будут.В обоих вариантах есть «за» и «против»:

  • A) Подобные соединения выполняются быстро, однако вы будете возвращать данные компании для каждой отдельной записи, что приводит к дополнительной нагрузке на трафик при связи сбаза данных.Это может быть проблемой, если сервер базы данных находится на отдельном сервере, или вы имеете дело с огромным набором данных.Помните, что даже если дополнительные данные кажутся небольшими, умножьте их на число ожидаемых одновременных посетителей веб-сайта, и вы, возможно, будете насыщать ссылку на свою базу данных.

    Пример, предоставленный @ abney317, точен, однако вместо этогосравнивая название компании, я бы сравнил cid, поскольку он не только будет более производительным, но и более надежным.

  • B) Это метод, который я бы выбрал,хотя он немного сложнее в реализации и требует двух запросов вместо одного, он является более масштабируемым и поддерживаемым вариантом в будущем.Это также сделает ваш код немного легче для отслеживания и отладки.

    Пример:

    // 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>";
    }
    

Несколько дополнительных замечаний:

  • Всегда используйте htmlspecialchars при выводе текста из базы данных, которая не должна содержать HTML, если вы не сделаете это, вы получите доступ к векторам атак XSS.

  • Я не использовал SQLэкранируйте идентификатор компании, так как в соответствии с вашей схемой базы данных это целое число, и поскольку оно не предоставляется конечным пользователем, его можно безопасно использовать напрямую, избегая каких-либо дополнительных накладных расходов на обработку.

0 голосов
/ 02 января 2019

Если вам нужно показать только несколько полей, попробуйте получить данные в одном запросе: 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 голосов
/ 02 января 2019

Поскольку вы делаете заказ по названию компании, вы сможете проверить, когда название компании изменилось, чтобы узнать, когда создавать новый контейнер.

$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>";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...