2013-05-16 3 views
1

Как выбрать строку в случайном порядке из запроса базы данных SQL? Под этим я имею в виду:Как выбрать случайную строку из SQL-запроса?

Выделить все вещи с категорией «зеленый» из table1:

$stmt = $db->query('SELECT * from table1 WHERE Category LIKE "%green%"'); 

Затем случайным образом отображать строку из этого выбора (в отличии от отображения каждой строки из этого выбора, как я сделал ниже)

while($rows = $stmt->fetch()){ 
    echo "<tr><td>". $rows['Number'] . "</td><td>" . $rows['Content'] . "</td></tr>"; 
}; 
+0

Вы хотите «случайный» ряд или «произвольный» ряд? Случайная строка обычно ссылается на равную вероятность возврата любой заданной строки в наборе. «Произвольная» строка означает, что вам все равно, какая строка. –

+0

@GordonLinoff Вы имеете в виду [это] (http://xkcd.com/221/)? –

+0

@GeorgeCummins. , , Объяснение слишком длинное для комментария. См. Мое решение ниже. –

ответ

5

В разумных размеров набора данных, заказать строки в случайном порядке и выберите первый один:

...ORDER BY RAND() LIMIT 1; 

Ваше заявление будет:

$stmt = $db->query(
    'SELECT * from table1 
    WHERE Category LIKE "%green%" 
    ORDER BY RAND() LIMIT 1;' 
); 

Если сузить выбор в запросе, вам не нужно будет использовать грязный процесс, чтобы извлечь одну строку из результирующего набора в вашем PHP коде.

Если набор данных очень велик, рассмотрим выполнение нескольких запросов в соответствии с рекомендациями Tobias Hagenbeek:

  1. COUNT() совпадающие строки.
  2. В PHP выберите случайное число между 1 и результатом COUNT().
  3. Выполнить новый запрос, чтобы выбрать указанную строку:

    ...LIMIT <random number>, 1;

Наконец, если вам нужен только один, произвольный ряд и хаотичность/уникальность не является проблемой, рассмотреть вопрос о выборе первой строки из таблицы каждый раз, как это было предложено Гордон Линофф:

...LIMIT 1; 
+1

использовать только «ORDER BY RAND» на небольшом наборе данных; его ужасно неэффективно –

+0

Даже если набор данных велик, вряд ли это будет быстрее, чем возвращение и разбор всего набора результатов? –

+0

да, но это не альтернатива –

0

Самый простой способ заключается в следующем:

$stmt = $db->query('SELECT * from table1 WHERE Category LIKE "%green%" ORDER BY RAND()'); 

ORDER BY RAND() будет производить заказ произвольно, но это немного дороже, чем операция (link).

Если вам небезразлично, вы можете запросить количество строк в таблице, затем выполните $r = rand(0, $count-1), а затем LIMIT 1 OFFSET $r в конце вашего запроса.

0

Вы можете использовать ORDER BY RAND(), но вы должны быть устали делать это. Особенно, если вы говорите о больших системах и более 10 тыс. Строк.

Вот почему ...

Что происходит при запуске такого запроса? Предположим, вы запустили этот запрос в таблице со 10000 строками, чем SQL-сервер генерирует 10000 случайных чисел, просматривает эти числа для самого маленького и дает вам эту строку. Генерация случайных чисел - относительно дорогостоящая операция, сканирование их для самой низкой (если у вас есть LIMIT 10, она должна будет найти 10 наименьших чисел) также не так быстро (если цитата - текст, она медленнее, если это что-то с фиксированным размером быстрее, возможно, из-за необходимости создания временной таблицы).

Так что вы должны сделать, это подсчет ваших строк, возьмите случайное число в диапазоне от 0 до Вашего кол-1, а затем сделать SELECT, столбец из таблицы LIMIT $ generated_number, 1

0

Если вы хотите только одну строку из множества всех строк, то самый быстрый способ просто:

SELECT * 
from table1 
WHERE Category LIKE "%green%" 
LIMIT 1; 

Это даст вам первую строку встречается в данных. В близком приближении это первая строка, вставленная в таблицу, которая соответствует вашим критериям. (Это не гарантия. Например, удаления определенно могут это изменить.)

Это имеет преимущество в том, fast'ish, что является полезным, потому что индекс не принесет пользу вам на пункте where. В этом случае запрос выполняет полное сканирование таблицы, но останавливается при первом совпадении.

Альтернатива для действительно случайной строки является использование rand():

SELECT * 
from table1 
WHERE Category LIKE "%green%" 
order by rand() 
limit 1; 

Это требует полного сканирования таблицы, которая не останавливается, потому что все матчи нужны для сортировки. Затем у вас есть дополнительные накладные расходы на сортировку подмножества на rand(). Есть несколько альтернатив, если производительность действительно является проблемой.

Смежные вопросы