Home » Mysql » How do I select random rows in MySQL?

How do I select random rows in MySQL?

Posted by: admin December 11, 2017 Leave a comment

Questions:
mytable

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

This is my table structure. Here I want to select randomly 4 rows so I use RAND() mysql function in my query
my questions is

How do I pair to rows. I mean, I wanna select pid 2 and 3 always one ofter another.
I need in bellow order. i don’t want to break the pair A2 A3

A1 A2 A3 A4 or A2 A3 A4 A1 or A2 A3 A4 A5 or A4 A5 A2 A3 and etc

I used the query below but it’s not working for me

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

turbod was close with his answer, he was just ordering randomly, when it seems you wanted to order by pid, after getting the random rows you wanted in conjunction with the ones concerning A2 and 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`

Questions:
Answers:

Generally, using ORDER BY RAND() is not a good idea. Please read the text by Jan Kneschke, showing why: http://jan.kneschke.de/projects/mysql/order-by-rand/

Questions:
Answers:

I ran a heavy test on this, passed.

(
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"

This will do the job very well. But to make the result even more random, execute that statement with replacing that 0.5 value in 1st line with a random value chosen by your client application code like mt_rand(0, 1000000) / 1000000 in PHP . Make sure it falls between 0 and 1. But do NOT use mysql function rand() in place of that 0.5 because it will make A2 and A3 apart from each other. The trick is assigning a random value for “ordercol” in all rows but keep it same for A2 and A3

EDIT:
I believe we can replace the 0.5 value with a LEFT JOIN even instead of relying on discrete value by PHP, as we replace the first segment of the union, so the whole query becomes:

(
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"

Questions:
Answers:

I doubt there is a sane way to this in MySQL only.

I can think of one way of doing it, assuming you are using PHP/MySQL:

Essentially you query everything but A3, then put A3 next to 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);
          }
      }

Now $data will contain your results in the desired order.

Questions:
Answers:

If you are always selecting all the rows in the table:

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;

If you are not always returning all the rows, thus need to check if A3 was returned to know if A2 should be included:

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;

Questions:
Answers:
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()

That should do it.

Questions:
Answers:

Here is my solution:

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()

Questions:
Answers:

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

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

i think this will satisfy your need.

Leave a Reply

Your email address will not be published. Required fields are marked *