Как избежать использования RAND () в запросе MySQL в Kohana 3 - PullRequest
1 голос
/ 06 мая 2010

У меня никогда не было необходимости делать произвольный SELECT для БД MySQL, пока этот проект не работает над мной. После исследования кажется, что обычные люди говорят, что использование RAND () - плохая идея. Я нашел статью, которая объясняет, как сделать другой тип случайного выбора.

В принципе, если я хочу выбрать пять (5) случайных элементов, я должен сделать следующее (я использую здесь фреймворк Кохана)?

<?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;
    }
}

Если нет, то какое решение лучше?

Ответы [ 2 ]

5 голосов
/ 06 мая 2010

Этот подход будет работать до тех пор, пока ваши offer_id являются последовательными и все непрерывными - если вы когда-либо удалите предложение, у вас могут быть пробелы в идентификаторах, которые могут стать проблемой.

0 голосов
/ 06 мая 2010

Я читал то же самое о функции MySQL rand () для больших наборов таблиц, но я думаю, что вы могли бы сделать это быстрее, посчитав строки таблицы, а затем используя встроенный в PHP rand (0, count) для генерации несколько идентификаторов индекса вы можете получить в SELECT. Я подозреваю, что это будет иметь тот же эффект, но без проблем с производительностью.

...