php - 做一段时间/循环以获得 10 个随机结果

标签 php mysql sql

您好,我正在尝试为我的网站制作标签脚本,这样每次搜索引擎访问我的网站时,我的网站上都会显示 10 个不同的标签。

这些标签将从数据库中获取。 所以此刻我已经对它进行了编码,所以它只抓取一个。 (因为我不知道如何做 while )

像这样

$sql = "SELECT tagname FROM tags ORDER BY rand() LIMIT 10";
$result = mysql_query($sql);
$row = mysql_fetch_object($result);
echo "<a href='index.php'>" .$row->tagname. " </a>";

无论如何我可以添加一段时间以便它执行 10 次吗?例如,使用相同的 echo 但打印出 10 个结果而不是 1 ....我已将限制从 1 更改为 10 但这没有用...仍然显示一个...

最佳答案

停止使用ORDER BY RAND()。停下来。此操作的复杂度为n*log2(n),这意味着查询所花费的时间会增长“

    entries  |  time units
  -------------------------
         10  |         1     /* if this takes 0.001s */
      1'000  |       300
  1'000'000  |   600'000     /* then this will need 10 minutes */

如果您想生成随机结果,请创建一个存储过程来生成它们。像这样的东西(代码取自 this article,你应该阅读):

DELIMITER $$
DROP PROCEDURE IF EXISTS get_rands$$
CREATE PROCEDURE get_rands(IN cnt INT)
BEGIN
  DROP TEMPORARY TABLE IF EXISTS rands;
  CREATE TEMPORARY TABLE rands ( tagname VARCHAR(63) );

loop_me: LOOP
    IF cnt < 1 THEN
      LEAVE loop_me;
    END IF;

    SET cnt = cnt - 1;

    INSERT INTO rands
       SELECT tags.tagname
         FROM tags 
         JOIN (SELECT (RAND()*(SELECT MAX(tags.id) FROM tags)) AS id) AS choices
        WHERE tags.id >= choices.id
        LIMIT 1;

  END LOOP loop_me;
END$$
DELIMITER ;

要使用它,您可以这样写:

CALL get_rands(10);
SELECT * FROM rands;

至于在 PHP 端执行这一切,您应该停止使用古老的 mysql_* API。它已有 10 多年历史,不再维护。社区甚至begun process贬低他们。 2012 年应该不会再有新代码用 mysql_* 编写了。相反,你应该使用 PDO。或 MySQLi .至于怎么写(用PDO):

// creates DB connection
$connection = new PDO('mysql:host=localhost;dbname=mydb;charset=UTF-8', 
                      'username', 'password');
$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

// executes the procedure and creates select statement
$connection->exec('CALL get_rands(10)');
$statement = $connection->query('SELECT * FROM rands');

// performs query and collects all the info
if ($statement->execute())
{
    $tags = $statement->fetchAll(PDO::FETCH::ASSOC);
}

更新

如果要求不仅要获得 10 个随机结果,而且要获得 10 个唯一的随机结果,则需要对 PROCEDURE 进行两处更改:

  1. 临时表应该强制条目的唯一性:

    CREATE TEMPORARY TABLE rands ( tagname VARCHAR(63) UNIQUE);
    

    仅收集 ID 而不是值也可能有意义。特别是如果您正在寻找 10 篇独特的文章,而不仅仅是标签。

  2. 当发现插入重复值时,cnt 计数器不应减少。这可以通过添加一个 HANDLER(在定义 LOOP 之前)来确保,这将“捕获”引发的警告,并调整计数器:

    DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET cnt = cnt + 1;
    

关于php - 做一段时间/循环以获得 10 个随机结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9945691/

相关文章:

java - 使用 hibernate 的点 "."不敏感搜索?

php - 如何在点击链接时调用同一页面上的php文件

c# - 无法打开数据库,因为它是 706 版本。此服务器支持 655 及更早版本。不支持降级路径

php - postgresql 不喜欢多个逗号

php - 删除 MySQLi 记录而不在 URL 中显示 id

mysql - DATE 类型的字段可以有带有 CURRENT_TIMESTAMP 的 DEFAULT 值吗?

Python:pandas read_sql_query

php - 服务器会同时处理两个或多个吗?

php - CodeIgniter - 如何检查 validation_error 数组中是否有任何内容

sql - 为什么 upsert 不是基本的 SQL 操作