在我的情况下避免循环内的查询

时间:2012-12-31 14:40:11

标签: php mysql loops select

我的情况非常复杂。我没有找到一种更好的方法来解决这个问题,而不是在我进入该页面时将一个SELECT查询放入一个滚动超过70000次的循环中(不用担心,我使用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_users表中获取其他内容,例如username,这需要另一个查询在那个循环中。

这太多了,我需要一种更简单的方法来解决这个问题。

有没有办法在进入循环之前获取那些user_id并在循环中使用它们?

这是imgit_images的表格结构: imgit_images table schema

虽然这是imgit_users的架构: imgit_users table schema

4 个答案:

答案 0 :(得分: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'];
}

您可能需要稍微调整一下(尚未测试过),但您似乎能够这样做,所以我并不担心!

答案 1 :(得分: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

这显然不能避免需要一个循环(你可能会使用字符串连接来构建你的where子句的IN部分,但你可能在这里使用了一个连接)但它会返回每次迭代的用户信息,并防止需要进一步迭代来获取用户的信息。

答案 2 :(得分:1)

不确定它是否会有所帮助,但我看到了一些可能的优化:

  1. 在循环外准备查询,并在循环内反弹/执行/获取结果。如果查询准备工作很昂贵,您可能会节省相当多的时间。

  2. 您可以像Passing an array to a query using a WHERE clause一样传递数组并获取图片和用户ID,这样您就可以将查询分段为少量查询。

答案 3 :(得分: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()。轻松完成,现在您可以从单个查询的单个结果集中获得所有所需数据。 (根据需要将其他列添加到查询的SELECT子句中。)