繁体   English   中英

while(mysql_fetch_array)在while循环中

[英]while (mysql_fetch_array) in a while loop

我有此代码:

while ($sum<16 || $sum>18){
$totala = 0;
$totalb = 0;
$totalc = 0;
$ranka = mysql_query("SELECT duration FROM table WHERE rank=1 ORDER BY rand() LIMIT 1");
$rankb = mysql_query("SELECT duration FROM table WHERE rank=2 ORDER BY rand() LIMIT 1");
$rankc = mysql_query("SELECT duration FROM table WHERE rank=3 ORDER BY rand() LIMIT 1");
while ($rowa = mysql_fetch_array($ranka)) {
    echo $rowa['duration'] . "<br/>";
    $totala = $totala + $rowa['duration'];
}
while ($rowb = mysql_fetch_array($rankb)) {
        $totalb = $totalb + $rowb['duration'];      
    }       
while ($rowc = mysql_fetch_array($rankc)) {
        $totalc = $totalc + $rowc['duration'];
    }

    $sum=$totala+$totalb+$totalc;
}
echo $sum;

它可以正常工作,但是问题是直到执行“ echo $ rowa ['duration']”的“ $ sum = 16”为止,问题是,在“ while( $ rowa = mysql_fetch_array($ ranka))“这是while循环吗? 因为大多数时候返回所有数字,直到“ $ sum = 16”

您在第一个内部while循环中显式地回显了$ rowa ['duration']。 如果您只想打印$ ranka集合中的最后一个持续时间,则只需将echo更改为$rowa_duration = $rowa['duration']然后在循环外回显即可。

while ($rowa = mysql_fetch_array($ranka)) {
    $rowa_duration = $rowa['duration'];
    $totala = $totala + $rowa['duration'];
}
echo $rowa_duration . '<br/>';

您在这里所做的事情在多个层面上都是不好的。 还有你的英语恐怖。 好..实践使完美。 您可以尝试在FreeNode服务器上加入## php聊天室。 那将提高您的英语和PHP技能。.它肯定对我有很大帮助。 反正..

SQL

首先,使用ORDER BY RAND()非常无知(至多)。 随着表开始变大,此操作将使查询变慢。 它具有n * log2(n)复杂度,这意味着选择具有1000个条目的查询表将比具有10个条目的查询表花费大约3000倍的时间。

要了解更多信息,您应该阅读此博客文章 ,但是对于您当前的查询,解决方案如下所示:

SELECT duration 
FROM table 
    JOIN (SELECT CEIL(RAND()*(SELECT MAX(id) FROM table)) AS id) as choice
WHERE 
    table.id >= choice.id
    rank = 1 
LIMIT 1

这将从表中选择随机duration

但是由于您实际上是在选择具有3个不同等级(1、2和3)的数据,因此创建包含三个查询的UNION会很有意义:

SELECT duration 
FROM table 
    JOIN (SELECT CEIL(RAND()*(SELECT MAX(id) FROM table)) AS id) as choice
WHERE 
    table.id >= choice.id
    rank = 1 
LIMIT 1
UNION ALL
SELECT duration 
FROM table 
    JOIN (SELECT CEIL(RAND()*(SELECT MAX(id) FROM table)) AS id) as choice
WHERE 
    table.id >= choice.id
    rank = 2 
LIMIT 1
UNION ALL
SELECT duration 
FROM table 
    JOIN (SELECT CEIL(RAND()*(SELECT MAX(id) FROM table)) AS id) as choice
WHERE 
    table.id >= choice.id
    rank = 3 
LIMIT 1

看起来很吓人,但实际上它会比您当前使用的要快,结果将是“ duration列中的三个条目。

PHP与SQL

  1. 您仍在使用旧的mysql_*函数访问数据库。 这种形式的API已有10多年的历史,在编写新代码时不应该使用。 不再维护(修复和/或改进)旧功能,甚至社区也已开始弃用这些功能。

    相反,您应该使用PDOMySQLi 使用哪种选项取决于您的个人喜好以及实际可用的选项。 我更喜欢PDO(因为命名参数和对其他RDBMS的支持),但这是一个主观的选择。

  2. php / mysql代码的另一个问题是您似乎毫无意义地循环了思想项目。 您的查询具有LIMIT 1 ,这意味着将只有一行。 循环毫无意义。

  3. 如果duration最大值为1则存在无限循环的可能性。 在循环开始时,您将有$sum === 15 ,它适合第一个while条件。 并且在该循环的最后,您可以拥有$sum === 18 ,它满足第二个循环条件...然后它变为无穷大,并且您的SQL Server受阻。

而且,如果您在duration中使用分数,那么3个新结果的总值需要更小。 刚刚超过2 15.99开始,以18.01结尾(持续时间额外增加2.02或每个持续时间下的0.7 )。 再次..无尽循环。

建议

这是我要怎么做:

$pdo = new PDO('mysql:dbname=my_db;host=localhost', 'username', 'password');
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$sum = 0;
while ( $sum < 16 )
{
    $query = 'that LARGE query above';
    $statement = $pdo->prepare( $query );
    if ( $statement->execute() )
    {
        $data = $statement->fetchAll( PDO::FETCH_ASSOC );
        $sum += $data[0]['duration']+$data[1]['duration']+$data[2]['duration'];
    }
}
echo $data[0]['duration'];

这应该执行您的代码所执行的操作..或至少我认为是您的意图。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM