6

サーバーのパフォーマンスが低下するため、ループ内でクエリ(選択)を使用することは悪い習慣であると言われました。

私は次のような配列を持っています

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

これらはたった3つのインデックスです。私が使用している配列は一定のサイズではないため、20個ものインデックスが含まれる場合があります。

今、私がやっていることは(これはすべてのコードではありませんが、基本的な考え方です)

  1. Forループ
  2. サーバーにクエリを実行し、「ロサンゼルス」に住むすべての人の名前を選択します
  3. 名前を印刷する

出力は次のようになります。

Los Angeles
      Michael Stern
      David Bloomer
      William Rod

New York
      Kary Mills

Chicago
      Henry Davidson
      Ellie Spears

後でテーブルが大きくなると多くのクエリが発生する可能性があるため、これは非常に非効率的な方法です。

だから私の質問は、どんなサイズでもよい配列内のものに基づいて情報を選択するためのより良い、より効率的な方法はありますか?

4

4 に答える 4

5

IN単一のクエリですべての結果を取得するクエリを使用します。

SELECT * FROM people WHERE town IN('LA', 'London', 'Paris')
于 2012-11-30T10:23:54.363 に答える
4

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 />";
    }
}

データベースの設計上の問題として、町の名前を別のテーブルに格納し、人物のテーブルには実際の町の名前ではなく町の ID を含める必要があります (検証がより簡単かつ迅速になり、検証によってレコードが失われる可能性が低くなります)。誰かが故郷の町を間違えたからです)

于 2012-11-30T10:27:42.403 に答える
1

@MrCode が言及しているように、MySQL のIN()演算子を使用して目的のすべての都市のレコードを一度に取得できますが、結果を主に都市別に並べ替えると、最後に見た都市を追跡し、新しい結果を出力する結果セットをループできます。最初に遭遇したときの都市。

PDOを MySQL の関数と一緒に使用FIELD()して、結果セットが元の配列と同じ順序であることを確認します (それを気にしない場合は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>';
}
于 2012-11-30T10:24:39.050 に答える
0

それが準備済みステートメントの目的です。プレースホルダーを値にバインドし、同じクエリで変数のように使用します。クエリが変更されていないため、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
}
于 2012-11-30T10:23:30.510 に答える