Как выбрать случайные строки в MySQL?

mytable

pid name field
=== ==== =====
1    A1   0
2    A2   1
3    A3   1
4    A4   0   
5    A5   0

Это моя таблица. Здесь я хочу выбрать случайно 4 строки, поэтому я использую функцию RAND() mysql в своем запросе мои вопросы

Как я соединяюсь с строками. Я имею в виду, я хочу выбрать pid 2 и 3 всегда один другой. Мне нужно в порядке. Я не хочу разбить пару A2 A3

A1 A2 A3 A4 или A2 A3 A4 A1 или A2 A3 A4 A5 или A4 A5 A2 A3 и т.д.

Я использовал запрос ниже, но он не работает для меня

SELECT * FROM mytable ORDER BY RAND() ASC limit 0,4

Ответ 1

turbod был близок с его ответом, он просто заказывал случайным образом, когда, похоже, вы хотели заказать pid, после получения случайных строк, которые вы хотели, в сочетании с теми, что касались A2 и A3:

(
    SELECT *
    FROM `mytable`
    WHERE 
        name ='A2' OR 
        name ='A3'
    LIMIT 2
)
UNION
(
    SELECT DISTINCT *
    FROM `mytable`
    WHERE 
        name !='A2' OR 
        name !='A3'
    ORDER BY RAND( ) LIMIT 2
) 
ORDER BY `pid`

Ответ 2

Как правило, использование ORDER BY RAND() не является хорошей идеей. Прочтите текст Яна Кнешке, в котором показано, почему: http://jan.kneschke.de/projects/mysql/order-by-rand/

Ответ 3

Я провел тяжелый тест на этом, прошел.

(
SELECT * , 0.5 AS ordercol
FROM `mytable`
WHERE `name`IN ( "A2", "A3" )
LIMIT 2
)
UNION (
SELECT * , rand() AS ordercol
FROM `mytable`
WHERE `name` NOT IN ( "A2", "A3" )
LIMIT 2
)
ORDER BY ordercol, `name` IN ( "A2", "A3" ) , `name` ="A3"

Это сделает работу очень хорошо. Но чтобы сделать результат еще более случайным, выполните этот оператор, заменив это значение 0.5 в 1-й строке случайным значением, выбранным вашим кодом клиентского приложения, например mt_rand(0, 1000000) / 1000000 в PHP. Убедитесь, что он падает между 0 и 1. Но НЕ используйте функцию mysql rand() вместо этого 0.5, потому что это сделает A2 и A3 отдельно друг от друга. Трюк присваивает случайное значение для "ordercol" во всех строках, но сохраняет его одинаковым для A2 и A3

EDIT: Я считаю, что мы можем заменить значение 0.5 LEFT JOIN даже вместо того, чтобы полагаться на дискретное значение PHP, поскольку мы заменяем первый сегмент объединения, поэтому весь запрос становится:

(
SELECT mt1.* , mt2.ordercol AS ordercol
FROM `mytable` AS mt1
LEFT JOIN (

SELECT RAND( ) AS ordercol
) AS mt2 ON TRUE
WHERE `name`
IN (
"A2", "A3"
)
LIMIT 2
)
UNION (
SELECT * , rand() AS ordercol
FROM `mytable`
WHERE `name` NOT IN ( "A2", "A3" )
LIMIT 2
)
ORDER BY ordercol, `name` IN ( "A2", "A3" ) , `name` ="A3"

Ответ 4

Я сомневаюсь, что в MySQL есть разумный способ.

Я могу думать об одном способе этого, предполагая, что вы используете PHP/MySQL:

По существу вы запрашиваете все, кроме A3, затем поместите A3 рядом с A2

$res = mysql_query("SELECT name, field FROM mytable WHERE name <> 'A3' ORDER BY RAND()");
$res2 = mysql_query("SELECT name, field FROM mytable WHERE name = 'A3'");

$data = array();
while($row = mysql_fetch_array($res))
      {
      array_push($data, $row);

      if ($row['name'] == "A2")
          {
          $row2 = mysql_fetch_array($res2);
          array_push($data, $row2);
          }
      }

Теперь данные $будут содержать ваши результаты в нужном порядке.

Ответ 5

Если вы всегда выбираете все строки в таблице:

SELECT pid, name, field, idx
FROM (
    SELECT pid, name, field,
        @pos := IF(name = 'A3', @idx, @pos),
        @idx := @idx + IF(name = 'A3', 2, 1), idx
    FROM mytable, (SELECT @pos = -1, @idx := 0) dm
    WHERE name <> 'A2'
    ORDER BY RAND()
)
UNION SELECT pid, name, field, @pos + 1 idx
FROM mytable
WHERE name = 'A2'
ORDER BY idx;

Если вы не всегда возвращаете все строки, вам нужно проверить, было ли возвращено A3, чтобы знать, следует ли включать A2:

SELECT pid, name, field, idx
FROM (
    SELECT pid, name, field,
        @pos := IF(name = 'A3', @idx, @pos),
        @idx := @idx + IF(name = 'A3', 2, 1), idx
    FROM mytable, (SELECT @pos = -1, @idx := 0) dm
    WHERE name <> 'A2'
    ORDER BY RAND()
    LIMIT 4
)
UNION SELECT pid, name, field, @pos + 1 idx
FROM mytable
WHERE @pos != -1 AND name = 'A2'
ORDER BY idx;

Ответ 6

SELECT * FROM (
  SELECT DISTINCT name FROM mytable
  WHERE name <> 'A2' AND name <> 'A3'
  ORDER BY RAND()
  LIMIT 0,2
UNION 
  SELECT DISTINCT name FROM mytable
  WHERE name = 'A2' OR name = 'A3'
  ORDER BY name
)whateverQueryAlias
ORDER BY RAND()

Это должно сделать это.

Ответ 7

Вот мое решение:

SELECT *
FROM `mytable`
WHERE name ='A2'
OR name ='A3'
LIMIT 2
UNION
(SELECT DISTINCT *
FROM `mytable`
WHERE name !='A2'
OR name !='A3'
ORDER BY RAND( ) LIMIT 2) ORDER BY RAND()

Ответ 8

SELECT *, RAND() "xrand" FROM yourtable A ORDER BY xrand LIMIT 4

Ответ 9

SELECT * FROM `mytable` order by rand(), name asc limit 4.

Я думаю, что это удовлетворит ваши потребности.