如何在MySQL中选择随机行?

时间:2011-02-24 11:41:08

标签: 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 A4A2 A3 A4 A1A2 A3 A4 A5A4 A5 A2 A3

我使用了下面的查询,但它不适合我

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

9 个答案:

答案 0 :(得分:11)

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`

答案 1 :(得分:6)

通常,使用ORDER BY RAND()不是一个好主意。请阅读Jan Kneschke的文字,说明原因:http://jan.kneschke.de/projects/mysql/order-by-rand/

答案 2 :(得分:2)

我对此进行了严格的测试,通过了。

(
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值替换为客户端应用程序代码(如PHP中的mt_rand(0, 1000000) / 1000000)选择的随机值。确保它介于0和1之间。但 NOT 使用mysql函数rand()代替0.5,因为它会使A2和A3彼此分开。 诀窍是在所有行中为“ordercol”分配一个随机值,但为A2和A3保持相同

编辑: 我相信我们可以用LEFT JOIN替换0.5值,而不是依靠PHP的离散值,因为我们替换了union的第一段,所以整个查询变为:

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

答案 3 :(得分:1)

我怀疑在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);
          }
      }

现在$ data将按所需顺序包含您的结果。

答案 4 :(得分:1)

如果您总是选择表格中的所有行:

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;

答案 5 :(得分:0)

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

应该这样做。

答案 6 :(得分:0)

这是我的解决方案:

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

答案 7 :(得分:0)

SELECT *,RAND()&#34; xrand&#34;来自yourtable A ORDER BY xrand LIMIT 4

答案 8 :(得分:-1)

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

我认为这将满足您的需求。