Готовый оператор, запрос и сортировка WHERE .. IN (..) с MySQL - PullRequest
19 голосов
/ 13 сентября 2010

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

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();
    }

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

Ответы [ 7 ]

21 голосов
/ 13 сентября 2010

вы можете сделать это следующим образом:

$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.

5 голосов
/ 24 апреля 2015

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

$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 голосов
/ 27 августа 2017

Была такая же проблема, и в дополнение к ответу @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();
3 голосов
/ 14 сентября 2010

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

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

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

1 голос
/ 13 сентября 2010

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

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

0 голосов
/ 07 января 2014

Рассматривали ли вы переписывание исходного запроса с помощью предложений JOIN и WHERE, чтобы получить IDS, необходимые для исключения необходимости предложения WHERE IN?Я пришел сюда с тем же вопросом, и после рассмотрения возможных решений я понял, что ВНУТРЕННЕЕ СОЕДИНЕНИЕ было моим решением.

0 голосов
/ 13 сентября 2010

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

...