Подготовленный оператор `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();
}
Но теперь мне придется сортировать результаты вручную. Есть ли у меня хорошие альтернативы?
Ответы
Ответ 1
вы могли бы сделать это следующим образом:
$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.
Ответ 2
Я считаю, что это самый простой ответ:
$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
Я добавлю в конечном итоге медленное и уродливое решение, которое, тем не менее, использует подготовленные инструкции для ЛЮБОГО количества элементов массива:) 3 утверждения универсальны для любого случая и могут быть повторно использованы повсюду.
-
CREATE TEMPORARY TABLE
Идентификаторы (
идентификатор INT );
-
INSERT INTO
ids VALUES(?);
это вставляет ваши идентификаторы
-
SELECT
id FROM
ids LEFT JOIN .... ;
использовать данные из других таблиц для сортировки списка ids
-
SELECT
id FROM
ids ;
выберите все обратно
В противном случае вам придется использовать IN (?,?,?,....
или отсортировать строки вручную. Лучшая идея - использовать простые MySQL-запросы или попытаться получить список идентификаторов, уже отсортированных так, как вам нравится.
Ответ 4
Альтернативой может быть использование функции usort PHP для объекта результата, но это "руководство".
Смотрите это:
Сортировка объекта в PHP
Ответ 5
Имела ту же проблему и в дополнение к ответу @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();
Ответ 6
Нет, это не рекомендуется, если вы хотите получить определенные записи из базы данных с помощью предложения ORDER BY
.
Ответ 7
Рассматривали ли вы переписывание исходного запроса с помощью предложения JOIN и WHERE, чтобы получить IDS, чтобы избежать необходимости в предложении WHERE IN? Я пришел сюда с тем же вопросом, и после рассмотрения возможных решений я понял, что INNER JOIN был моим решением.