避免在 Kohana 3 的 MySQL 查询中使用 RAND()

发布于 2024-09-01 04:48:43 字数 1645 浏览 6 评论 0原文

在我正在从事的这个项目之前,我从未需要在 MySQL 数据库上进行随机 SELECT。经过研究后,似乎大多数人都说使用 RAND() 是一个坏主意。我发现一篇文章解释了如何进行另一种类型的随机选择。

基本上,如果我想选择五 (5) 个随机元素,我应该执行以下操作(我在这里使用 Kohana 框架)?

<?php
final class Offers extends Model
{
    /**
     * Loads a random set of offers.
     *
     * @param  integer  $limit
     * @return array
     */
    public function random_offers($limit = 5)
    {
        // Find the highest offer_id
        $sql = '
            SELECT MAX(offer_id) AS max_offer_id
              FROM offers
        ';
        $max_offer_id = DB::query(Database::SELECT, $sql)
            ->execute($this->_db)
            ->get('max_offer_id');

        // Check to make sure we're not trying to load more offers
        // than there really is...
        if ($max_offer_id < $limit)
        {
            $limit = $max_offer_id;
        }

        $used = array();
        $ids = '';
        for ($i = 0; $i < $limit; )
        {
            $rand = mt_rand(1, $max_offer_id);
            if (!isset($used[$rand]))
            {
                // Flag the ID as used
                $used[$rand] = TRUE;

                // Set the ID
                if ($i > 0) $ids .= ',';
                $ids .= $rand;

                ++$i;
            }
        }

        $sql = '
            SELECT offer_id, offer_name
              FROM offers
             WHERE offer_id IN(:ids)
        ';
        $offers = DB::query(Database::SELECT, $sql)
            ->param(':ids', $ids)
            ->as_object();
            ->execute($this->_db);

        return $offers;
    }
}

如果没有,什么是更好的解决方案?

I have never had a need to do a random SELECT on a MySQL DB until this project I'm working on. After researching it seems the general populous says that using RAND() is a bad idea. I found an article that explains how to do another type of random select.

Basically, if I want to select five (5) random elements, I should do the following (I'm using the Kohana framework here)?

<?php
final class Offers extends Model
{
    /**
     * Loads a random set of offers.
     *
     * @param  integer  $limit
     * @return array
     */
    public function random_offers($limit = 5)
    {
        // Find the highest offer_id
        $sql = '
            SELECT MAX(offer_id) AS max_offer_id
              FROM offers
        ';
        $max_offer_id = DB::query(Database::SELECT, $sql)
            ->execute($this->_db)
            ->get('max_offer_id');

        // Check to make sure we're not trying to load more offers
        // than there really is...
        if ($max_offer_id < $limit)
        {
            $limit = $max_offer_id;
        }

        $used = array();
        $ids = '';
        for ($i = 0; $i < $limit; )
        {
            $rand = mt_rand(1, $max_offer_id);
            if (!isset($used[$rand]))
            {
                // Flag the ID as used
                $used[$rand] = TRUE;

                // Set the ID
                if ($i > 0) $ids .= ',';
                $ids .= $rand;

                ++$i;
            }
        }

        $sql = '
            SELECT offer_id, offer_name
              FROM offers
             WHERE offer_id IN(:ids)
        ';
        $offers = DB::query(Database::SELECT, $sql)
            ->param(':ids', $ids)
            ->as_object();
            ->execute($this->_db);

        return $offers;
    }
}

If not, what is a better solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

2024-09-08 04:48:43

只要您的 Offer_id 是连续的且连续的,这种方法就会起作用 - 如果您删除了某个报价,则 id 中可能会存在间隙,这将成为问题。

That approach will work, as long as your offer_id's are sequential and all continuous - if you ever remove an offer, you might have gaps in the id's that would then be a problem.

一梦等七年七年为一梦 2024-09-08 04:48:43

我读过关于大型表集上的 MySQL rand() 函数的相同内容,但我认为您可以通过计算表行数,然后使用 PHP 内置的 rand(0, count) 生成一些索引来更快地完成它您可以在 SELECT 中获取 ID。我怀疑它会产生相同的影响,但不会出现所有性能问题。

I've read the same things about the MySQL rand() function on large table sets, but I would think you could do it faster by counting the table rows, then using PHP's built in rand(0, count) to generate a few index ID's you can grab in a SELECT. I suspect it would have the same affect but without all the performance concerns.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文