4

私はここでかなり複雑な状況にあります。そのページに入るときに70000回以上ロールオーバーするループ内にSELECTクエリを配置しない限り、これを解決するためのより良い方法を見つけることはできません(心配しないでください、私array_chunkは配列をページに分割するために使用します)。ここでクエリを使用すると、これはリソースキラーになると思います。このため、ここで質問をします。

私はループする必要があるこの大きな配列を持っています:

$images = scandir($imgit_root_path . '/' . IMAGES_PATH);

$indexhtm = array_search('index.htm', $images);
unset($images[0], $images[1], $images[$indexhtm]);

これで、内のファイル(画像)のすべてのファイル名を含む配列ができましたIMAGES_PATH。ここで問題が発生します。

登録ユーザーの画像が私のデータベースにリストされているため、これらの画像の一部はデータベースに登録されています。user_id次に、上記の配列で指定された画像名に基づいてを取得する必要があります。

ループ内で私は単にこれをしました:

foreach ($images as $image_name)
{
    $query = $db->prepare('SELECT user_id FROM imgit_images WHERE image_name = :name');
    $query->bindValue(':name', $image_name, PDO::PARAM_STR);
    $query->execute();
    $row = $query->fetch(PDO::FETCH_ASSOC);
    $user_id = $row['user_id'];

    echo $user_id;
}

これは問題なく機能しますが、効率は0になります。これを使用して、ループ内で別のクエリが必要になるなどuser_id、テーブルから他のものを取得することを計画しています。imgit_usersusername

これは多すぎるので、これに対処するためのより簡単な方法が必要です。

ループ内に入る前にそれらを取得user_idしてループ内で使用する方法はありますか?

これはからのテーブル構造ですimgit_imagesimgit_imagesテーブルスキーマ

これは次のスキーマですがimgit_usersimgit_usersテーブルスキーマ

4

4 に答える 4

3

このようなものは機能します(WHERE IN値の数が不明であるため、クエリを準備できるかどうかはわかりません...それ以外の場合は、必ずサナタイズしてください$images):

$image_names = "'".implode("', '", $images)."'";
$query = $db->prepare("SELECT img.user_id, image_name, username 
                         FROM imgit_images img
                         INNER JOIN imgit_users u ON u.user_id = img.user_id 
                         WHERE image_name IN(".$image_names.")");
$query->execute();
while($row = $query->fetch(PDO::FETCH_ASSOC))
{
    echo $row['user_id']."'s image is ".$row['image_name'];
}

少し調整する必要があるかもしれませんが(まだテストしていません)、できるようですので、心配はいりません。

于 2012-12-31T14:54:13.113 に答える
1

それが役立つかどうかはわかりませんが、可能性のあるいくつかの最適化が見られます。

  1. ループの外側でクエリを準備し、ループ内で結果をリバウンド/実行/取得します。クエリの準備に費用がかかる場合は、かなりの時間を節約できる可能性があります。

  2. WHERE句を使用して配列をクエリに渡す場合と同様に、配列を渡すことができ、画像とユーザーIDを取得できます。これにより、クエリを少数のクエリに断片化できる場合があります。

于 2012-12-31T14:49:26.937 に答える
1

クエリでを使用するだけでなくINNER JOIN、ループを繰り返すたびに、対応するユーザーの詳細が返されます。クエリを次のようなものに変更します(ここではテーブルの構造について仮定しています):

SELECT imgit_users.user_id 
,imgit_users.username
,imgit_users.other_column_and_so_on
FROM imgit_images 
INNER JOIN imgit_users ON imgit_users.user_id = imgit_images.user_id
WHERE imgit_images.image_name = :name

これは明らかにループの必要性を回避しません(おそらく文字列連結を使用しINてwhere句の一部を構築できますが、とにかくここで結合を使用する可能性があります)が、反復ごとにユーザーの情報を返します。ユーザーの情報を取得するためにさらに反復する必要がないようにします。

于 2012-12-31T14:48:46.063 に答える
0

PDOを使用すると、クエリを安全に作成できます。

$placeholders = implode(',', array_fill(0, count($images), '?'));
$sql = "SELECT u.username 
        FROM imgit_images i
        INNER JOIN imgit_users u ON i.user_id = u.id
        WHERE i.image_name IN ({$placeholders})";
$stmt = $db->prepare($sql);
$stmt->execute($images);

while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    // use $row['username']
}

カンマ区切りの文字列を作成し、?それらをIN'の括弧に書き込みます。次に、画像の配列をに渡しexecute()ます。簡単に実行でき、必要なすべてのデータを1つのクエリから1つの結果セットで利用できるようになりました。(必要に応じて、クエリのSELECT句に列を追加します。)

于 2019-06-22T12:56:26.623 に答える