-1

我正在尝试执行一个查询,该查询从图像表中删除过滤器表中不存在的所有文件。我正在跳过数据库中的 3,500 个最新文件,以便将表“修剪”回过滤器表中的 3,500 +“X”条记录。

filters 表包含文件的标记,以及 images 表中使用的文件 id。

该代码将在 cron 作业上运行。

我的代码:

$sql = mysql_query("SELECT * FROM `images` ORDER BY `id` DESC") or die(mysql_error());

while($row = mysql_fetch_array($sql)){
    $id = $row['id'];
    $file = $row['url'];

    $getId = mysql_query("SELECT `id` FROM `filter` WHERE `img_id` = '".$id."'") or die(mysql_error());
    if(mysql_num_rows($getId) == 0){        
        $IdQue[] = $id;
        $FileQue[] = $file;
    }
}
for($i=3500; $i<$x; $i++){
    mysql_query("DELETE FROM `images` WHERE id='".$IdQue[$i]."' LIMIT 1") or die("line 18".mysql_error());
    unlink($FileQue[$i]) or die("file Not deleted");
}
echo ($i-3500)." files deleted.";

输出:0 个文件被删除。

数据库内容:

images table: 10,000 rows
filters table: 63 rows

过滤器表中包含图像表 id 的行数:63 php 脚本的执行时间:4 秒 +/- 0.5 秒

相关数据库结构

  • 表:图像
  • ID
  • 网址
  • ETC...

  • 表:过滤器

  • ID
  • img_id(包含来自图像表的 ID)
  • ETC...
4

2 回答 2

1
 for($i=3500; $i<$x; $i++){

如果$x < 3500. 你可能想要:

 for($i=3500; $i<($x + 3500); $i++){

重新阅读有关 SQL 的文档JOIN也是一个好主意。

于 2012-10-16T22:39:24.027 回答
1

根据 Brendan 的回答,您可以构建一个subquery。您的整个脚本可能看起来像:

$query = mysql_query(
   "DELETE FROM `images` WHERE `id` NOT IN (
       SELECT `id` from `filter`
    ) ORDER BY `id` DESC LIMIT 3500,12340283492834
") or die(mysql_error());

printf("Files deleted: %d\n", mysql_affected_rows());

子查询(SELECT `id` from `filter` LIMIT 3500,12340283492834)首先解析并将一个 id 列表返回给父查询以在WHERE子句中使用。然后,您通过传入偏移量来保留最后 3500 行(因此它会跳过前 3500 行,然后删除其余行)。注意丑陋的LIMIT 3500,12340283492834......这是因为 MySQL 不支持无限制的偏移量。

完成后,运行选择查询以获取所有图像 URL,然后遍历文件系统上的图像,如果文件名不在结果数组中,则将其删除。

于 2012-10-16T22:41:14.067 回答