【问题标题】:loop a mysql query循环一个mysql查询
【发布时间】:2023-04-09 14:49:02
【问题描述】:

伙计们,我真的需要一些帮助。 2天我已经完全卡住了。我需要一个方向来接受这个,因为我正在做的显然是行不通的,我变得非常沮丧。

我的总体目标是限制发送到目标域的电子邮件数量(如果在数据库中设置为限制)。这背后的原因是最大化从邮件服务器发送的电子邮件数量 + 能够根据跳出率和其他因素调整节流设置。

例如,如果我将 gmail 和 yahoo 的节流速率设置为“100”,它将提取最多 100 条记录(如“gmail”)和最多 100 条记录(如“雅虎”)并继续发送它们。但是,如果没有更多要处理的限制域,请将 $rest_max 拉到它们不像 $throttle_domain 的地方并继续发送它们。

问题 #1 - 我如何一遍又一遍地循环第一个查询,直到 $throttle_domain 用尽?

问题 #2 - 我将如何提取与节流域不匹配的记录以及如何将其与此相关联?

编辑 忘了提到下面的代码可以正常工作,除了它只会拉 1 个油门记录并停止。

        $rest_max = '200';

        // this is where i need to loop!?
        $query = "SELECT * FROM `mailer_lists` WHERE `email` LIKE '%".$throttle_domain."' LIMIT ".$trim_speed."" ;
        $result = mysql_query($query) or die(mysql_error());
        while($row = mysql_fetch_array($result)){
        $email = $row['email'];
        $project = $row['project_name'];

        $querya = "SELECT * FROM `mailer_controller` WHERE `project_name` = '".$project."'" ;
        $resulta = mysql_query($querya) or die(mysql_error());
        while($rowa = mysql_fetch_array($resulta)){
        $project_name = $rowa['project_name'];
        $from_name = $rowa['from_name'];
        $from_email = $rowa['from_name']."@".$node_domain;
        $subject = $rowa['subject'];
        $body = $rowa['body'];
        $content = addslashes($body);

    // set header
    $header_from = 'From: '.$from_name.' <'.$from_email.'>';
    $header_reply_to = '-f  '.$from_email;

    // send mail
    mail($email,$subject,$body,$header_from,$header_reply_to);


    // delete contact from list only if it gets sent.
    mysql_query("DELETE FROM mailer_lists WHERE `project_name` = '".$project_name."' AND `email` = '$email' ") or die(mysql_error());  
    }}

【问题讨论】:

  • 为什么需要循环播放?您可以通过一个查询返回所有内容。
  • 我该怎么做呢?我已经阅读了一些提到 mysql 查询中的内爆函数的帖子,但不确定在这种情况下它是如何工作的。你是这个意思吗?
  • 约翰,我感觉你是新手。 ;) 这不是诽谤,我们在这里都是朋友。我还怀疑,一旦您从另一个角度看待这个问题,您就会拍自己的额头并获得程序员的升级。我将在这里发布答案,因为我的代码示例不适合评论框,但我不确定它是否真的能解决你的问题。

标签: php mysql loops


【解决方案1】:

这应该会删除不必要的循环和额外的查询,这可能无法解决您的所有问题,但可能会对您有所帮助。

我没有测试过这段代码,所以一定要先在测试环境中运行它,以确保我没有犯一个可能导致数据丢失的简单错误,由于查询的性质,我把这个免责声明,请先使用测试数据进行测试

    $rest_max = '200';

    $query = "SELECT * 
        FROM `mailer_lists` ml  
            JOIN `mailer_controller` mc ON ml.project_name = mc.project_name
        WHERE `email` LIKE '%".$throttle_domain."' LIMIT ".$trim_speed."" ;

    $result = mysql_query($query) or die(mysql_error());
    $delete=array();

    while($row = mysql_fetch_assoc($result)){
        $email = $row['email'];
        $project_name = $rowa['project_name'];
        $from_name = $rowa['from_name'];
        $from_email = $rowa['from_name']."@".$node_domain;
        $subject = $rowa['subject'];
        $body = $rowa['body'];
        $content = addslashes($body);

    // set header
    $header_from = 'From: '.$from_name.' <'.$from_email.'>';
    $header_reply_to = '-f  '.$from_email;

    // send mail
    mail($email,$subject,$body,$header_from,$header_reply_to);


    $delete[] = " (project_name = '$project_name' AND email = '$email') ";
}

if (!empty($delete)) {
    mysql_query("DELETE FROM mailer_lists 
        WHERE " . implode(' OR ', $delete)) or die(mysql_error());  
}

一个简单的测试方法是注释掉mail 部分并将DELETE FROM 更改为SELECT * FROM 并回显来自选择的内容,以确保出现应该删除的正确数据。

请阅读以下内容

然而,更好的删除方法是使用表格ID 字段并将其存储在$delete 中。因为这将缓解OR 语句并最大限度地减少意外删除有效行的错误。以下是它的工作原理(只是使用了结尾,将 ID 替换为您的 id 字段:

    $delete[] = $row['id'];
}

if (!empty($delete)) {
    mysql_query("DELETE FROM mailer_lists 
        WHERE id IN(" . implode(', ', $delete) . ")") or die(mysql_error());  
}

更新

我不确定这会运行多快,等等。但一种可能的方法是:

    // Fill the array however you want to with the domains. this is just an example
    $throttle = array('domain1.com', 'domain2.com', 'domain3.com');
    $query = "SELECT * 
        FROM `mailer_lists` ml  
            JOIN `mailer_controller` mc ON ml.project_name = mc.project_name
        WHERE `email` LIKE '%". implode("' OR `email` LIKE '%", $throttle) . "'  LIMIT ".$trim_speed." ORDER BY project_name, email";

同样,这是未经测试的,我不确定它在性能方面的匹配度如何。但是有一些东西让你测试。

编辑:更改为fetch_assoc,与fetch_array相对应

【讨论】:

  • 好的,首先我非常喜欢您将其整合到一个查询中的方式。我唯一的问题是 $throttle_domain 和 $throttle_speed 可能有 100 的值。我应该使用 foreach 循环它还是我可以内爆查询,以便它会提取所有限制域的记录,然后邮寄它们?
  • 查看更新。我不确定这是否是更好的方法,或者只是循环遍历 $throttle 数组。你必须做一些测试才能看到。
【解决方案2】:

你为什么不按照这些思路做点约翰:

    $rest_max = '200';
    $email = array();
    $project = array();

    $query = "SELECT * FROM `mailer_lists`, `mailer_controller` WHERE mailer_lists.project_name = mailer_controller.project_name AND `email` LIKE '%".$throttle_domain."' LIMIT ".$trim_speed."" ;
    $result = mysql_query($query) or die(mysql_error());
    $count = mysql_num_rows($result);
    while($row = mysql_fetch_array($result)){
    $email[] = $row['email'];
    $project[] = $row['project_name'];
    }
    $rest_max = $rest_max - $count;
    if($rest_max > 0)
    {
            //repeat the process with the new domain
    }

您可以使用连接同时执行两个查询,并利用 mysql_num_rows 查看从 Select 返回的结果数量,并使用它来确定您是否已经达到 200 个结果。你也可以把整个事情放在一个 for 循环中,但是如果你只使用上面提到的 2 个域,这将是最好的方法

【讨论】:

  • 要获取不在列表中的电子邮件,您只需使用 NOT LIKE 而不是 LIKE
【解决方案3】:

据我所知,您正在这样做:

$query = "SELECT * FROM `mailer_lists` WHERE `email` LIKE '%".$throttle_domain."' LIMIT ".$trim_speed."" ;

你可以在哪里这样做:

$query = "SELECT * FROM `mailer_lists` WHERE `email` LIKE '%$throttle_domain';";

我已经用内联变量 ("string $variable morestring") 替换了你的连接 ("string ".$variable." morestring"),因为它在没有 IDE 突出显示的情况下更容易理解。它仍然是正确的语法,你的 PHP 解释器会很好。但是到实际的变化:省略 LIMIT 子句。

通过删除 LIMIT,您将立即返回所有内容。这是一件好事,因为这意味着不是每次运行脚本时都执行 n 查询,而是运行两个查询。这也很好,因为它可以一次获得所有结果。

然后您可以使用 mysql_fetch_array 遍历结果,或者您可以 - 这太棒了 - 使用类似 mysql_fetch_all 之类的函数将整个结果转换为标准数组。出于某种原因,mysql_fetch_all 不是 PHP MySQL 模块的一部分,但在此处的 cmets 中发布了实现:

http://php.net/manual/en/function.mysql-fetch-array.php

然后,您会将整个搜索结果作为一个易于访问的键控数组。性感而简单。

【讨论】:

  • 我让它完美运行的方式。我遇到的问题是我正在限制 200 个域。这意味着 $throttle_domain = 200 个单独的域。唯一的问题是我只执行 1 次查询,因此它只会拉 1 个目标域并仅向一个目标域发送邮件,永远不会查询下一个目标域。我只是觉得一次循环 200 个查询似乎有点荒谬。
  • 一次循环通过 200 个查询 - 如果该脚本必须并行运行,将会对您的服务器造成伤害。多久会使用一次?它是偶尔运行的管理工具还是一直运行的工具?
猜你喜欢
  • 2013-11-23
  • 1970-01-01
  • 2015-02-15
  • 1970-01-01
  • 2013-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多