2010-05-21 2 views
28

Я хотел бы взять базу данных, скажем, 1000 пользователей и выбрать 20 случайных (ORDER BY rand(), LIMIT 20), а затем заказать результирующий набор по именам. Я придумал следующий запрос: не работает так, как я надеялся.MySQL ORDER BY rand(), имя ASC

SELECT * FROM users WHERE 1 ORDER BY rand(), name ASC LIMIT 20

+0

Что именно не работает для вас? – kgiannakakis

+0

Когда я попробую заказать rand() limit 3 в базе данных здесь из 1600 пользователей, я последовательно получаю случайные результаты. – vfilby

+0

@vfilby: Да, теперь попробуйте 'order by rand(), имя asc', и вы увидите, что оно не сортируется по имени. –

ответ

50

Используйте подзапрос:

SELECT * FROM 
(
    SELECT * FROM users ORDER BY rand() LIMIT 20 
) T1 
ORDER BY name 

Внутренний запрос выбирает 20 пользователей случайным образом и внешний запрос приказывает выбранных пользователей по имени.

+2

Удивительно, две вещи. Почему 'T1' после запроса, в чем его цель? Второе: вы знаете, можно ли использовать подзапрос в datamapper? –

+0

А, так вы выбрали этот внутренний выбор как новую временную таблицу. Понял. –

+4

@Josh K: Что касается вашего первого вопроса, это называется псевдонимом. Если вы опустите это, вы получите эту ошибку: «Каждая производная таблица должна иметь свой собственный псевдоним». –

2
SELECT * 
FROM (
     SELECT * 
     FROM users 
     WHERE 1 
     ORDER BY 
       rand() 
     LIMIT 20 
     ) q 
ORDER BY 
     name 
2

Используйте подзапрос:

SELECT * FROM (
    SELECT * FROM users ORDER BY RAND() LIMIT 20 
) u 
ORDER BY name 

или присоединиться к себе:

SELECT * FROM users u1 
INNER JOIN (
    SELECT id FROM users ORDER BY RAND() LIMIT 20 
) u2 USING(id) 
ORDER BY u1.name 
8

Осторожно ORDER BY RAND() из-за производительности и результатов. Проверьте эту статью: http://jan.kneschke.de/projects/mysql/order-by-rand/

+0

Согласитесь, возможно, это самый худший запрос. – mhughes

+0

Дополнительные ограничения WHERE ставят нагрузку RAND примерно на максимум 500 строк. Это не огромная таблица, производительность не является проблемой. –

9

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

SELECT COUNT(id) FROM users; #id is the primary key 

Затем получите случайные двадцать строк.

$start_row = mt_rand(0, $total_rows - 20); 

Окончательный запрос:

SELECT * FROM users ORDER BY name ASC LIMIT $start_row, 20; 
+0

Я считаю, что это должен быть правильный ответ, просто потому, что я думаю, что ресурсы могут быть ниже, чем вызов RAND() или использование «подзапроса». – Decoded

+2

Вы всегда будете получать 20 последовательных пользователей («последовательно» в отношении их имен), а не 20 случайных. – Pharaoh

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