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

And*_*lis 1 php mysql random kohana-3

在我正在研究这个项目之前,我从来没有需要在MySQL数据库上进行随机选择.在研究之后,人们普遍认为使用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Amb*_*ber 5

只要你的offer_id是连续的并且都是连续的,那么这种方法是有效的 - 如果你删除了一个提议,你可能在id中存在间隙,这将是一个问题.

  • 而不是做`$ rand = rand(); SELECT WHERE id = $ rand`(伪代码),你做`$ rand = rand(); SELECT WHERE id> $ rand LIMIT 1`如果你的id空间稀疏. (3认同)