Подготовленный оператор `WHERE .. IN (..)` запрос и сортировка – с MySQL

Представьте, что у нас есть запрос:

SELECT * FROM somewhere WHERE `id` IN(1,5,18,25) ORDER BY `name`; 

и массив идентификаторов для извлечения: $ids = array(1,5,18,25)

В подготовленных заявлениях рекомендуется подготовить одно заявление и называть его несколько раз:

 $stmt = $mysqli->prepare('SELECT * FROM somewhere WHERE `id`=?;'); foreach ($ids as $id){ $stmt->bind_params('i', $id); $stmt->exec(); } 

Но теперь мне придется сортировать результаты вручную. Есть ли у меня хорошие альтернативы?

Solutions Collecting From Web of "Подготовленный оператор `WHERE .. IN (..)` запрос и сортировка – с MySQL"

вы можете сделать это так:

 $ids = array(1,5,18,25); // creates a string containing ?,?,? $clause = implode(',', array_fill(0, count($ids), '?')); $stmt = $mysqli->prepare('SELECT * FROM somewhere WHERE `id` IN (' . $clause . ') ORDER BY `name`;'); call_user_func_array(array($stmt, 'bind_param'), $ids); $stmt->execute(); // loop through results 

Используя это, вы вызываете bind_param для каждого идентификатора, и у вас есть сортировка, выполняемая mysql.

Я считаю, что это самый простой ответ:

 $ids = [1,2,3,4,5]; $pdos = $pdo->prepare("SELECT * FROM somwhere WHERE id IN (:" . implode(',:', array_keys($ids)) . ") ORDER BY id"); foreach ($ids as $k => $id) { $pdos->bindValue(":". $k, $id); } $pdos->execute(); $results = $pdos->fetchAll(); 

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

Я добавлю в конечном итоге медленное и уродливое решение, которое, тем не менее, использует подготовленные инструкции для ЛЮБОГО количества элементов массива :). 3 утверждения универсальны для любого случая и могут быть повторно использованы повсюду.

  1. CREATE TEMPORARY TABLE идентификаторы ( id INT );
  2. INSERT INTO ids VALUES(?); это добавит ваши идентификаторы
  3. SELECT id FROM ids LEFT JOIN .... ; использовать данные из других таблиц для сортировки списка ids
  4. SELECT id FROM id ; выбрать все назад

В противном случае вам придется использовать IN (?,?,?,.... или сортировать строки вручную. Лучше всего использовать простые MySQL-запросы или попытаться получить список идентификаторов, уже отсортированных в пути тебе нравится.

Нет, это не рекомендуется, если вы хотите получить определенные записи из базы данных, используя предложение ORDER BY .

Альтернативой может быть использование функции usort PHP для объекта результата, но это «руководство».

См. Так: Сортировка объекта в PHP

Имела та же проблема и в дополнение к ответу @sled 7 лет назад, здесь есть возможность без создания call_user_func_array(array($stmt, 'bind_param'), $ids); шаг, но только вызовите bind_params один раз:

 $ids = array(1,5,18,25); // creates a string containing ?,?,? $bindClause = implode(',', array_fill(0, count($ids), '?')); //create a string for the bind param just containing the right amount of iii $bindString = str_repeat('i', count($ids)); $stmt = $mysqli->prepare('SELECT * FROM somewhere WHERE `id` IN (' . $bindClause . ') ORDER BY `name`;'); $stmt->bind_params($bindString, ...$ids); $stmt->execute(); 

Рассматривали ли вы переписывание исходного запроса с помощью предложения JOIN и WHERE, чтобы получить IDS, чтобы избежать необходимости в предложении WHERE IN? Я пришел сюда с тем же вопросом, и после рассмотрения возможных решений я понял, что INNER JOIN был моим решением.