PHP Альтернатива использованию запроса в цикле

Мне было сказано, что использовать цикл запроса (select) в цикле плохо, потому что он замедляет производительность сервера.

У меня есть массив, такой как

Array ( [1] => Los Angeles ) Array ( [2] =>New York) Array ( [3] => Chicago ) 

Это всего лишь 3 индекса. Массив, который я использую, не имеет постоянного размера, поэтому иногда он может содержать до 20 индексов.

Прямо сейчас, что я делаю (это не весь код, а основная идея)

  1. Для цикла
  2. запросить сервер и выбрать имена всех людей, которые живут в «Лос-Анджелесе»,
  3. Распечатайте имена

Результат будет выглядеть так:

 Los Angeles Michael Stern David Bloomer William Rod New York Kary Mills Chicago Henry Davidson Ellie Spears 

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

Итак, мой вопрос: есть ли более эффективный и эффективный способ ВЫБРАТЬ информацию, основанную на материале внутри массива, который может быть любого размера?

Чтобы добавить к ответу MrCodes, если вы начинаете с массива:

 $Cities = array(1=>'Los Angeles', 2=>'New York', 3=>'Chicago'); $query = "SELECT town, personname FROM people WHERE town IN('".implode("','", $Cities)."') ORDER BY town"; if ($sql = $mysqliconnection->prepare($query)) { $sql->execute(); $result = $sql->get_result(); $PrevCity = ''; while ($row = $result->fetch_assoc()) { if ($row['town'] != $PrevCity) { echo $row['town']."<br />"; $PrevCity = $row['town']; } echo $row['personname']."<br />"; } } 

В качестве проблемы с дизайном базы данных вы, вероятно, должны иметь названия городов в отдельной таблице, а таблица для человека содержит идентификатор города, а не фактическое название города (упрощает процедуру проверки, быстрее и с проверкой, менее вероятной для пропусков записей потому что кто-то ошибся их родной город)

Используйте запрос IN , который захватит все результаты в одном запросе:

 SELECT * FROM people WHERE town IN('LA', 'London', 'Paris') 

Как упоминает @MrCode , вы можете использовать оператор MySQL IN() для получения записей для всех желаемых городов за один раз, но если вы затем отсортируете результаты в основном по городу, вы можете прокрутить список результатов, отслеживая последний увиденный город и выводящий новый город, когда он впервые встречается.

Используя PDO вместе с функцией FIELD() MySQL, чтобы гарантировать, что набор результатов находится в том же порядке, что и ваш исходный массив (если вас это не волнует, вы можете просто сделать ORDER BY city , что было бы намного более эффективным, особенно с подходящим индексом в столбце city ):

 $arr = ['Los Angeles', 'New York', 'Chicago']; $placeholders = rtrim(str_repeat('?, ', count($arr)), ', '); $dbh = new PDO("mysql:dbname=$dbname", $username, $password); $qry = $dbh->prepare(" SELECT city, name FROM my_table WHERE city IN ($placeholders) ORDER BY FIELD(city, $placeholders) "); if ($qry->execute(array_merge($arr, $arr))) { // output headers echo '<ul>'; $row = $qry->fetch(); while ($row) { $current_city = $row['city']; // output $current_city initialisation echo '<li>'.htmlentities($current_city).'</li><ul>'; do { // output name $row echo '<li>'.htmlentities($row['name']).'</li>'; } while ($row = $qry->fetch() and $row['city'] == $current_city); // output $current_city termination echo '</ul>'; } // output footers echo '</ul>'; } 

Это цель подготовленных заявлений. Вы привязываете местозаполнитель к значению и используете его как переменную с тем же запросом. Поскольку запрос не изменился, вы минимизируете связь с сервером mysql, что приводит к повышению эффективности.

Пример использования PDO:

 $cities = array( "Los Angeles", "New York", "Chicago" ); try { //Change database parameters here (user, pass, database name) $db = new PDO("mysql:host=localhost;dbname=users", "user", "pass"); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $stmt = $db->prepare("SELECT * FROM `users` WHERE `city` = :city"); foreach ($cities as $city) { $stmt->bindValue(":city", $city); $stmt->execute(); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); //Output data here. You can format it however you'd like var_dump($city, $result); } } catch (PDOException $e) { //Error handling here }