while(mysql_fetch_array)在while循环中

时间:2012-03-20 22:26:41

标签: php mysql

我有这段代码:

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;

它工作正常,但问题是直到“$ sum = 16”“echo $ rowa ['duration']”执行,问题是,是否有“回显”只有最新执行的代码“while($ rowa = mysql_fetch_array($ ranka))”我这个循环? 因为大多数时间都返回所有数字,直到“$ sum = 16”

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

你在做什么在多个层面都很糟糕。你的英国人很可怕。嗯......练习很完美。您可以尝试在FreeNode服务器上加入## php聊天室。这将提高你的英语和PHP技能..它确实帮助了我很多。无论如何..

SQL

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

要了解有关它的更多信息,请阅读this blog post,但对于您当前的查询,解决方案如下:

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 with SQL

  1. 您仍在使用旧的mysql_*函数来访问数据库。在编写新代码时,这种形式的API已超过10年,不应使用。旧功能不再维护(修复和/或改进),甚至社区已开始process of deprecating所述功能。

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

  2. 你的php / mysql代码的其他问题是你似乎无意义地循环思考项目。您的查询有LIMIT 1,这意味着只有一行。没有必要制作一个循环。

  3. 如果duration的最大值为1,则可能会出现无限循环。在循环开始时,您将$sum === 15符合第一个while条件。并且在循环结束时,您可以拥有$sum === 18,它满足第二个循环条件......然后它将关闭到无穷大并且您的SQL服务器会阻塞。

  4. 如果您使用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'];
    

    这应该做你的代码所做的......或者至少,我认为,是你的意图。