web-dev-qa-db-ja.com

プリペアドステートメント、 `WHERE .. IN(..)`クエリと並べ替え— MySQLを使用

クエリがあると想像してください:

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

フェッチするIDの配列:$ids = array(1,5,18,25)

プリペアドステートメントでは、 adviced 1つのステートメントを準備し、それを複数回呼び出すことです。

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

ただし、結果を手動で並べ替える必要があります。素敵な代替品はありますか?

22
kolypto

あなたはこのようにそれを行うことができます:

$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

これを使用して、IDごとにbind_paramを呼び出し、mysqlによってソートが実行されます。

24
sled

同じ問題があり、7年前の@sledの回答に加えて、call_user_func_array(array($stmt, 'bind_param'), $ids);ステップを実行せずに、bind_paramsを1回だけ呼び出す可能性があります。

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

私はこれが可能な限り最も簡単な答えだと信じています:

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

IDの配列にキーまたは不正な文字を含むキーが含まれていない限り、機能します。

6
Martin J.

最終的に遅くて醜いソリューションを追加しますが、それでも、任意の数の配列項目に対してプリペアドステートメントを使用します:) 3つのステートメントはどのような場合でも普遍的であり、どこでも再利用できます。

  1. _CREATE TEMPORARY TABLE_ ids _(_ id _INT );_
  2. _INSERT INTO_ idsVALUES(?);これによりIDが挿入されます
  3. SELECTid FROMids _LEFT JOIN .... ;_他のテーブルのデータを使用してidsリストを並べ替える
  4. SELECTid FROMids _;_すべてを選択し直します

それ以外の場合は、_IN (?,?,?,...._を使用するか、行を手動で並べ替える必要があります。最良のアイデアは、単純なMySQLクエリを使用するか、または、すでに好きな方法でソートされているIDのリストを取得することです。

3
kolypto

別の方法は、結果オブジェクトでPHP usort関数を使用することですが、これは「手動」です。

これを参照してください: PHPでオブジェクトを並べ替える

1
Ryan Schumacher

WHERE IN句の必要性を回避するために必要なIDSを取得するために、JOIN句とWHERE句を使用して元のクエリを書き換えることを検討しましたか?私は同じ質問でここに来ました、そして可能な解決策を検討した後、私は内部結合が私の解決策であることに気づきました。

0
zeros-and-ones

いいえ、ORDER BY句を使用してデータベースから特定のレコードをフェッチする場合は、お勧めしません。

0