Ответы:
Отличный пост, обрабатывающий несколько случаев, от простых до пропусков, до неоднородных с пропусками.
http://jan.kneschke.de/projects/mysql/order-by-rand/
Для наиболее общего случая вот как вы это делаете:
SELECT name
FROM random AS r1 JOIN
(SELECT CEIL(RAND() *
(SELECT MAX(id)
FROM random)) AS id)
AS r2
WHERE r1.id >= r2.id
ORDER BY r1.id ASC
LIMIT 1
Это предполагает, что распределение идентификаторов одинаково, и что в списке идентификаторов могут быть пробелы. Смотрите статью для более продвинутых примеров
mysqli_fetch_assoc($result)
? Или эти 10 результатов не обязательно различимы?
SELECT column FROM table
ORDER BY RAND()
LIMIT 10
Не эффективное решение, но работает
ORDER BY RAND()
относительно медленно
SELECT words, transcription, translation, sound FROM vocabulary WHERE menu_id=$menuId ORDER BY RAND() LIMIT 10
занимает 0,0010, без LIMIT 10 - 0,0012 (в этой таблице 3500 слов).
Простой запрос, который имеет отличную производительность и работает с пробелами :
SELECT * FROM tbl AS t1 JOIN (SELECT id FROM tbl ORDER BY RAND() LIMIT 10) as t2 ON t1.id=t2.id
Этот запрос на 200K таблице занимает 0.08s и нормальную версию (SELECT * FROM TBL ORDER BY RAND () LIMIT 10) принимает 0.35s на моей машине.
Это быстро, потому что на этапе сортировки используется только индексированный столбец идентификаторов. Вы можете увидеть это поведение в объяснении:
ВЫБЕРИТЕ * ОТ ТАБЛИЧНОГО ЗАКАЗА ПО RAND () LIMIT 10:
ВЫБЕРИТЕ * ОТ tbl КАК t1 ПРИСОЕДИНЯЙТЕСЬ (ВЫБЕРИТЕ идентификатор ОТ tbl ЗАКАЗАТЬ ПО RAND () LIMIT 10) при t2 ON t1.id = t2.id
Взвешенная версия : https://stackoverflow.com/a/41577458/893432
Я получаю быстрые запросы (около 0,5 секунд) с медленным процессором , выбирая 10 случайных строк в регистрах 400 КБ базы данных MySQL без кэширования размером 2 ГБ. Смотрите здесь мой код: Быстрый выбор случайных строк в MySQL
<?php
$time= microtime_float();
$sql='SELECT COUNT(*) FROM pages';
$rquery= BD_Ejecutar($sql);
list($num_records)=mysql_fetch_row($rquery);
mysql_free_result($rquery);
$sql="SELECT id FROM pages WHERE RAND()*$num_records<20
ORDER BY RAND() LIMIT 0,10";
$rquery= BD_Ejecutar($sql);
while(list($id)=mysql_fetch_row($rquery)){
if($id_in) $id_in.=",$id";
else $id_in="$id";
}
mysql_free_result($rquery);
$sql="SELECT id,url FROM pages WHERE id IN($id_in)";
$rquery= BD_Ejecutar($sql);
while(list($id,$url)=mysql_fetch_row($rquery)){
logger("$id, $url",1);
}
mysql_free_result($rquery);
$time= microtime_float()-$time;
logger("num_records=$num_records",1);
logger("$id_in",1);
logger("Time elapsed: <b>$time segundos</b>",1);
?>
ORDER BY RAND()
FLUSH STATUS; SELECT ...; SHOW SESSION STATUS LIKE 'Handler%';
чтобы увидеть это.
ORDER BY RAND()
заключается в том, что он сортирует только идентификаторы (не полные строки), поэтому временная таблица меньше, но все равно должна сортировать их все.
Это очень простой и однострочный запрос.
SELECT * FROM Table_Name ORDER BY RAND() LIMIT 0,10;
order by rand()
очень медленно, если стол большой
Из книги:
Выберите случайную строку, используя смещение
Еще один метод, который позволяет избежать проблем, обнаруженных в предыдущих альтернативах, заключается в подсчете строк в наборе данных и возврате случайного числа между 0 и счетчиком. Затем используйте это число в качестве смещения при запросе набора данных
<?php
$rand = "SELECT ROUND(RAND() * (SELECT COUNT(*) FROM Bugs))";
$offset = $pdo->query($rand)->fetch(PDO::FETCH_ASSOC);
$sql = "SELECT * FROM Bugs LIMIT 1 OFFSET :offset";
$stmt = $pdo->prepare($sql);
$stmt->execute( $offset );
$rand_bug = $stmt->fetch();
Используйте это решение, если вы не можете использовать смежные значения ключей, и вам нужно убедиться, что у каждой строки есть равный шанс выбора.
SELECT count(*)
становится медленным.
Как выбрать случайные строки из таблицы:
Отсюда: выберите случайные строки в MySQL
Быстрое улучшение по сравнению с «сканированием таблицы» заключается в использовании индекса для выбора случайных идентификаторов.
SELECT *
FROM random, (
SELECT id AS sid
FROM random
ORDER BY RAND( )
LIMIT 10
) tmp
WHERE random.id = tmp.sid;
PRIMARY KEY
).
Хорошо, если у вас нет пробелов в ваших ключах, и они все числовые, вы можете вычислить случайные числа и выбрать эти строки. но это, вероятно, не так.
Таким образом, одним из решений будет следующее:
SELECT * FROM table WHERE key >= FLOOR(RAND()*MAX(id)) LIMIT 1
это в основном гарантирует, что вы получите случайное число в диапазоне ваших ключей, а затем выберете следующий лучший, который больше. Вы должны сделать это 10 раз.
однако это не случайно, потому что ваши ключи, скорее всего, не будут распределяться равномерно.
Это действительно большая проблема, и ее нелегко решить, выполнив все требования, MySQL rand () - лучшее, что вы можете получить, если вам действительно нужно 10 случайных строк.
Однако есть другое решение, которое быстро, но также имеет компромисс, когда дело доходит до случайности, но может подойти вам лучше. Прочитайте об этом здесь: Как я могу оптимизировать функцию ORDER BY RAND () в MySQL?
Вопрос в том, насколько случайным он вам нужен.
Можете ли вы объяснить немного больше, чтобы я мог дать вам хорошее решение.
Например, у компании, с которой я работал, было решение, в котором они нуждались в абсолютной случайности очень быстро. Они закончили с предварительным заполнением базы данных случайными значениями, которые были выбраны по убыванию и впоследствии снова установлены на разные случайные значения.
Если вы вряд ли когда-либо обновите, вы также можете заполнить инкрементный идентификатор, чтобы у вас не было пробелов и вы могли просто вычислить случайные ключи перед выбором ... Это зависит от варианта использования!
Id
и все ваши случайные запросы вернут вам этот Id
.
FLOOR(RAND()*MAX(id))
склонен к возвращению больших идентификаторов.
Мне нужен был запрос, чтобы вернуть большое количество случайных строк из довольно большой таблицы. Это то, что я придумал. Сначала получите максимальный идентификатор записи:
SELECT MAX(id) FROM table_name;
Затем подставьте это значение в:
SELECT * FROM table_name WHERE id > FLOOR(RAND() * max) LIMIT n;
Где max - максимальный идентификатор записи в таблице, а n - количество строк, которые вы хотите в вашем наборе результатов. Предполагается, что в идентификаторах записей нет пробелов, хотя я сомневаюсь, что это повлияет на результат, если они были (хотя я и не пробовал). Я также создал эту хранимую процедуру, чтобы быть более общей; передайте имя таблицы и количество возвращаемых строк. Я использую MySQL 5.5.38 в Windows 2008, 32 ГБ, двойной EHz50 с частотой 3 ГГц и в таблице с 17 361 264 строками, она достаточно стабильна при ~ 0,03 с / 11 с и возвращает 1 000 000 строк. (время из MySQL Workbench 6.1; вы также можете использовать CEIL вместо FLOOR во втором операторе выбора в зависимости от ваших предпочтений)
DELIMITER $$
USE [schema name] $$
DROP PROCEDURE IF EXISTS `random_rows` $$
CREATE PROCEDURE `random_rows`(IN tab_name VARCHAR(64), IN num_rows INT)
BEGIN
SET @t = CONCAT('SET @max=(SELECT MAX(id) FROM ',tab_name,')');
PREPARE stmt FROM @t;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @t = CONCAT(
'SELECT * FROM ',
tab_name,
' WHERE id>FLOOR(RAND()*@max) LIMIT ',
num_rows);
PREPARE stmt FROM @t;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
$$
тогда
CALL [schema name].random_rows([table name], n);
Все лучшие ответы уже опубликованы (в основном те, на которые ссылается ссылка http://jan.kneschke.de/projects/mysql/order-by-rand/ ).
Я хочу указать еще одну возможность ускорения - кэширование . Подумайте, почему вам нужно получить случайные строки. Вероятно, вы хотите разместить на сайте какой-нибудь случайный пост или случайную рекламу. Если вы получаете 100 запросов в секунду, действительно ли нужно, чтобы каждый посетитель получал случайные строки? Обычно вполне нормально кэшировать эти X случайных строк в течение 1 секунды (или даже 10 секунд). Не имеет значения, если 100 уникальных посетителей в одну и ту же секунду получат одинаковые случайные записи, потому что в следующую секунду еще 100 посетителей получат другой набор сообщений.
При использовании этого кэширования вы также можете использовать некоторые из более медленных решений для получения случайных данных, так как они будут выбираться из MySQL только один раз в секунду независимо от ваших запросов / с.
Я улучшил ответ @Riedsio. Это наиболее эффективный запрос, который я могу найти в большой равномерно распределенной таблице с пробелами (проверено на получение 1000 случайных строк из таблицы, в которой> 2,6 Б строк).
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max := (SELECT MAX(id) FROM table)) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1)
Позвольте мне распаковать, что происходит.
@max := (SELECT MAX(id) FROM table)
MAX(id)
каждый раз, когда вам нужна строкаSELECT FLOOR(rand() * @max) + 1 as rand)
SELECT id FROM table INNER JOIN (...) on id > rand LIMIT 1
Выполнение объединения поможет вам вписать все в один запрос, чтобы избежать выполнения нескольких запросов. Это также позволяет вам сэкономить на расчетах MAX(id)
. В зависимости от вашего приложения, это может иметь большое значение или очень мало.
Обратите внимание, что это получает только идентификаторы и получает их в случайном порядке. Если вы хотите сделать что-то более сложное, я рекомендую вам сделать это:
SELECT t.id, t.name -- etc, etc
FROM table t
INNER JOIN (
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max := (SELECT MAX(id) FROM table)) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1)
) x ON x.id = t.id
ORDER BY t.id
LIMIT 1
чтобы LIMIT 30
везде в запросе
LIMIT 1
чтобы LIMIT 30
получить 30 записей подряд из случайной точки в таблице. Вместо этого у вас должно быть 30 копий (SELECT id FROM ....
части в середине.
Riedsio
ответить. Я пытался с 500 попаданиями в секунду на страницу, используя PHP 7.0.22 и MariaDB на centos 7, с Riedsio
ответом я получил 500+ дополнительных успешных ответов, затем ваш ответ.
Я использовал этот http://jan.kneschke.de/projects/mysql/order-by-rand/, опубликованный Riedsio (я использовал случай хранимой процедуры, которая возвращает одно или несколько случайных значений):
DROP TEMPORARY TABLE IF EXISTS rands;
CREATE TEMPORARY TABLE rands ( rand_id INT );
loop_me: LOOP
IF cnt < 1 THEN
LEAVE loop_me;
END IF;
INSERT INTO rands
SELECT r1.id
FROM random AS r1 JOIN
(SELECT (RAND() *
(SELECT MAX(id)
FROM random)) AS id)
AS r2
WHERE r1.id >= r2.id
ORDER BY r1.id ASC
LIMIT 1;
SET cnt = cnt - 1;
END LOOP loop_me;
В этой статье он решает проблему пропусков в идентификаторах, приводящих к не столь случайным результатам, путем ведения таблицы (с использованием триггеров и т. Д. См. Статью); Я решаю проблему, добавив в таблицу еще один столбец, заполненный непрерывными числами, начиная с 1 ( правка: этот столбец добавляется во временную таблицу, созданную подзапросом во время выполнения, не влияет на вашу постоянную таблицу):
DROP TEMPORARY TABLE IF EXISTS rands;
CREATE TEMPORARY TABLE rands ( rand_id INT );
loop_me: LOOP
IF cnt < 1 THEN
LEAVE loop_me;
END IF;
SET @no_gaps_id := 0;
INSERT INTO rands
SELECT r1.id
FROM (SELECT id, @no_gaps_id := @no_gaps_id + 1 AS no_gaps_id FROM random) AS r1 JOIN
(SELECT (RAND() *
(SELECT COUNT(*)
FROM random)) AS id)
AS r2
WHERE r1.no_gaps_id >= r2.id
ORDER BY r1.no_gaps_id ASC
LIMIT 1;
SET cnt = cnt - 1;
END LOOP loop_me;
В статье я вижу, что он пошел на все, чтобы оптимизировать код; у меня нет никаких идей, если / насколько мои изменения повлияют на производительность, но работают очень хорошо для меня.
@no_gaps_id
индекса не может быть использован, так что если вы посмотрите на EXPLAIN
ваш запрос, у вас есть Using filesort
и Using where
(без индекса) для подзапросов, в отличии от исходного запроса.
Вот изменитель игры, который может быть полезным для многих;
У меня есть таблица с 200k строк, с последовательными идентификаторами , мне нужно было выбрать N случайных строк, поэтому я решил генерировать случайные значения на основе наибольшего идентификатора в таблице, я создал этот скрипт, чтобы выяснить, какая операция быстрее всего:
logTime();
query("SELECT COUNT(id) FROM tbl");
logTime();
query("SELECT MAX(id) FROM tbl");
logTime();
query("SELECT id FROM tbl ORDER BY id DESC LIMIT 1");
logTime();
Результаты:
36.8418693542479
мс0.241041183472
мс0.216960906982
мсОсновываясь на этих результатах, order desc является самой быстрой операцией для получения максимального идентификатора.
Вот мой ответ на вопрос:
SELECT GROUP_CONCAT(n SEPARATOR ',') g FROM (
SELECT FLOOR(RAND() * (
SELECT id FROM tbl ORDER BY id DESC LIMIT 1
)) n FROM tbl LIMIT 10) a
...
SELECT * FROM tbl WHERE id IN ($result);
К вашему сведению: чтобы получить 10 случайных строк из таблицы 200k, мне потребовалось 1,78 мс (включая все операции на стороне php)
LIMIT
немного увеличить - вы можете получить дубликаты.
Это супер быстро и на 100% случайно, даже если у вас есть пробелы.
x
доступных вам строкSELECT COUNT(*) as rows FROM TABLE
a_1,a_2,...,a_10
от 0 доx
SELECT * FROM TABLE LIMIT 1 offset a_i
для i = 1, ..., 10Я нашел этот взлом в книге « Антипаттерны SQL» от Билла Карвина .
SELECT column FROM table ORDER BY RAND() LIMIT 10
находится в O (nlog (n)). Так что да, это быстрое решение, и оно работает для любого распространения идентификаторов.
x
. Я бы сказал, что это не случайное поколение из 10 строк. В моем ответе вы должны выполнить запрос в шаге три 10 раз, то есть каждый получает только одну строку за выполнение и не должен беспокоиться, если смещение находится в конце таблицы.
Объедините ответ @redsio с temp-таблицей (600K не так уж много):
DROP TEMPORARY TABLE IF EXISTS tmp_randorder;
CREATE TABLE tmp_randorder (id int(11) not null auto_increment primary key, data_id int(11));
INSERT INTO tmp_randorder (data_id) select id from datatable;
А затем возьмите версию @redsios. Ответ:
SELECT dt.*
FROM
(SELECT (RAND() *
(SELECT MAX(id)
FROM tmp_randorder)) AS id)
AS rnd
INNER JOIN tmp_randorder rndo on rndo.id between rnd.id - 10 and rnd.id + 10
INNER JOIN datatable AS dt on dt.id = rndo.data_id
ORDER BY abs(rndo.id - rnd.id)
LIMIT 1;
Если стол большой, вы можете просеять первую часть:
INSERT INTO tmp_randorder (data_id) select id from datatable where rand() < 0.01;
Версия: Вы можете сохранить таблицу tmp_randorder
постоянной, назовите ее datatable_idlist. Повторно создавайте эту таблицу через определенные промежутки времени (день, час), так как она также будет иметь дыры. Если ваш стол становится действительно большим, вы также можете заполнить отверстия
выберите l.data_id как целое из списка данных lidatatatable dt для dt.id = l.data_id, где dt.id равен нулю;
Версия: Дайте вашему набору данных столбец random_sortorder либо непосредственно в datatable, либо в постоянной дополнительной таблице datatable_sortorder
. Индексируйте этот столбец. Создайте случайное значение в вашем приложении (я назову это $rand
).
select l.*
from datatable l
order by abs(random_sortorder - $rand) desc
limit 1;
Это решение различает «крайние строки» с самым высоким и самым низким random_sortorder, поэтому переставляйте их с интервалами (один раз в день).
Другим простым решением будет ранжирование строк и выборка одной из них случайным образом, и с этим решением вам не нужно будет иметь столбец на основе 'Id' в таблице.
SELECT d.* FROM (
SELECT t.*, @rownum := @rownum + 1 AS rank
FROM mytable AS t,
(SELECT @rownum := 0) AS r,
(SELECT @cnt := (SELECT RAND() * (SELECT COUNT(*) FROM mytable))) AS n
) d WHERE rank >= @cnt LIMIT 10;
Вы можете изменить предельное значение в соответствии с вашими потребностями, чтобы получить доступ к столько строк, сколько вы хотите, но в большинстве случаев это будут последовательные значения.
Однако, если вам не нужны последовательные случайные значения, вы можете выбрать большую выборку и выбрать ее случайным образом. что-то вроде ...
SELECT * FROM (
SELECT d.* FROM (
SELECT c.*, @rownum := @rownum + 1 AS rank
FROM buildbrain.`commits` AS c,
(SELECT @rownum := 0) AS r,
(SELECT @cnt := (SELECT RAND() * (SELECT COUNT(*) FROM buildbrain.`commits`))) AS rnd
) d
WHERE rank >= @cnt LIMIT 10000
) t ORDER BY RAND() LIMIT 10;
Один способ, который я нахожу довольно хорошим, если есть автоматически сгенерированный идентификатор, это использовать оператор по модулю "%". Например, если вам нужно 10 000 случайных записей из 70 000, вы можете упростить это, сказав, что вам нужна 1 из каждых 7 строк. Это может быть упрощено в этом запросе:
SELECT * FROM
table
WHERE
id %
FLOOR(
(SELECT count(1) FROM table)
/ 10000
) = 0;
Если результат деления целевых строк на общее количество не является целым числом, у вас будет несколько дополнительных строк, чем то, что вы просили, поэтому вы должны добавить предложение LIMIT, чтобы помочь вам обрезать результирующий набор следующим образом:
SELECT * FROM
table
WHERE
id %
FLOOR(
(SELECT count(1) FROM table)
/ 10000
) = 0
LIMIT 10000;
Это требует полного сканирования, но это быстрее, чем ORDER BY RAND, и, на мой взгляд, проще для понимания, чем другие опции, упомянутые в этой теме. Также, если система, которая записывает в БД, создает наборы строк в пакетах, вы можете не получить такой случайный результат, как ожидали.
Если вы хотите одну случайную запись (независимо от того, есть ли пробелы между идентификаторами):
PREPARE stmt FROM 'SELECT * FROM `table_name` LIMIT 1 OFFSET ?';
SET @count = (SELECT
FLOOR(RAND() * COUNT(*))
FROM `table_name`);
EXECUTE stmt USING @count;
Я просмотрел все ответы, и я не думаю, что кто-то вообще упоминает эту возможность, и я не уверен, почему.
Если вам нужна предельная простота и скорость при минимальных затратах, то, мне кажется, имеет смысл хранить случайное число для каждой строки в БД. Просто создайте дополнительный столбец random_number
и установите для него значение по умолчанию RAND()
. Создайте индекс для этого столбца.
Затем, когда вы хотите извлечь строку, сгенерируйте случайное число в вашем коде (PHP, Perl и т. Д.) И сравните его со столбцом.
SELECT FROM tbl WHERE random_number >= :random LIMIT 1
Я предполагаю, что хотя это очень аккуратно для одной строки, для десяти строк, таких как ОП, вас попросят вызвать его десять раз (или придумать хитрый твик, который сразу ускользает от меня)
Следующее должно быть быстрым, беспристрастным и независимым от столбца id. Однако это не гарантирует, что количество возвращаемых строк будет соответствовать количеству запрошенных строк.
SELECT *
FROM t
WHERE RAND() < (SELECT 10 / COUNT(*) FROM t)
Объяснение: если вы хотите, чтобы 10 строк из 100, то каждая строка имела 1/10 вероятности получения SELECT, чего можно достичь WHERE RAND() < 0.1
. Этот подход не гарантирует 10 строк; но если запрос выполняется достаточно раз, среднее число строк на выполнение будет около 10, и каждая строка в таблице будет выбрана равномерно.
PREPARE stm from 'select * from table limit 10 offset ?';
SET @total = (select count(*) from table);
SET @_offset = FLOOR(RAND() * @total);
EXECUTE stm using @_offset;
Вы также можете применить предложение where как
PREPARE stm from 'select * from table where available=true limit 10 offset ?';
SET @total = (select count(*) from table where available=true);
SET @_offset = FLOOR(RAND() * @total);
EXECUTE stm using @_offset;
Протестировано на 600 000 строк (700 МБ). Выполнение запроса таблицы заняло ~ 0,016 с жесткого диска.
--EDIT--
Смещение может принимать значение, близкое к концу таблицы, что приведет к тому, что оператор select вернет меньше строк (или, возможно, только 1 строка), чтобы избежать этого, мы можем проверить еще offset
раз после объявления этого, например, так
SET @rows_count = 10;
PREPARE stm from "select * from table where available=true limit ? offset ?";
SET @total = (select count(*) from table where available=true);
SET @_offset = FLOOR(RAND() * @total);
SET @_offset = (SELECT IF(@total-@_offset<@rows_count,@_offset-@rows_count,@_offset));
SET @_offset = (SELECT IF(@_offset<0,0,@_offset));
EXECUTE stm using @rows_count,@_offset;
Я использую этот запрос:
select floor(RAND() * (SELECT MAX(key) FROM table)) from table limit 10
время запроса: 0.016с
Вот как я это делаю:
select *
from table_with_600k_rows
where rand() < 10/600000
limit 10
Мне нравится это, потому что не требует других таблиц, это просто написать, и это очень быстро выполнить.
Используйте приведенный ниже простой запрос, чтобы получить случайные данные из таблицы.
SELECT user_firstname ,
COUNT(DISTINCT usr_fk_id) cnt
FROM userdetails
GROUP BY usr_fk_id
ORDER BY cnt ASC
LIMIT 10
Я думаю, это самый лучший способ ..
SELECT id, id * RAND( ) AS random_no, first_name, last_name
FROM user
ORDER BY random_no