ORDER BY RAND()用于多列(垂直每列的随机内容)

时间:2016-04-22 18:39:22

标签: php mysql random subquery multiple-columns

我正在寻找一个mysql解决方案,让几个列从该列输出一个随机字段。

我现在的查询只是随机选择整行,但不随机化分隔的列。

$sql = "SELECT col1, col2, col3, col4 FROM table ORDER BY RAND() limit 4";

我尝试过子查询,但我对此并不熟悉,所以如果有人可以提供帮助......

4 个答案:

答案 0 :(得分:2)

试试这个:

SELECT CASE rnd
          WHEN 1 THEN col1
          WHEN 2 THEN col2
          WHEN 3 THEN col3
          WHEN 4 THEN col4       
       END AS col          
FROM (       
  SELECT col1, col2, col3, col4,
         FLOOR(RAND() * 4) + 1 AS rnd
  FROM mytable 
ORDER BY RAND() ) AS t

表达式FLOOR(RAND() * 4) + 1生成1到4(含)之间的随机数。外部查询使用此数字随机选择表中的4列之一。

Demo here

修改

如果您想要随机播放列,可以使用以下查询:

SELECT CASE FIND_IN_SET(1, rnd)
          WHEN 1 THEN col1
          WHEN 2 THEN col2
          WHEN 3 THEN col3
          WHEN 4 THEN col4
       END AS c1,
       CASE FIND_IN_SET(2, rnd)
          WHEN 1 THEN col1
          WHEN 2 THEN col2
          WHEN 3 THEN col3
          WHEN 4 THEN col4
       END AS c2,
       CASE FIND_IN_SET(3, rnd)
          WHEN 1 THEN col1
          WHEN 2 THEN col2
          WHEN 3 THEN col3
          WHEN 4 THEN col4
       END AS c3,
       CASE FIND_IN_SET(4, rnd)
          WHEN 1 THEN col1
          WHEN 2 THEN col2
          WHEN 3 THEN col3
          WHEN 4 THEN col4
       END AS c4
FROM (  
  SELECT col1, col2, col3, col4, 
         (SELECT GROUP_CONCAT(i ORDER BY RAND()) 
          FROM (SELECT 1 AS i UNION ALL SELECT 2 UNION ALL 
                SELECT 3 UNION ALL SELECT 4) t) AS  rnd
  FROM mytable) AS t

Demo here

答案 1 :(得分:1)

我认为如果你在PHP中随机化列也会更简单,但作为一个有趣的挑战,我想我会像下面这样做。 它将随机提供4行并随机化/随机化列值。

将它简单地打为GROUP_CONCAT值1,2,3,4但随机化顺序..然后使用FIND_IN_SET提取数字索引。然后使用ELT()函数选择基于这些索引的col值。

SELECT 
       ELT(FIND_IN_SET(1,rand_indexes),col1,col2,col3,col4) as col1,
       ELT(FIND_IN_SET(2,rand_indexes),col1,col2,col3,col4) as col2,
       ELT(FIND_IN_SET(3,rand_indexes),col1,col2,col3,col4) as col3,
       ELT(FIND_IN_SET(4,rand_indexes),col1,col2,col3,col4) as col4
FROM 
  (SELECT col1,col2,col3,col4,
     (SELECT GROUP_CONCAT(i ORDER BY RAND()) as indexes FROM
       (SELECT 1 as i UNION SELECT 2 UNION SELECT 3 UNION SELECT 4)indexes
      )as rand_indexes
   FROM `table`
   )T1 
ORDER BY RAND() limit 4

sqlfiddle

更新如果您想像在评论中提到的那样垂直地对列进行随机播放,那么您可以使用此查询。 它基本上以随机顺序选择第一列4行,然后与第二列的4个随机行连接,依此类推......

SELECT T1.col1,T2.col2,T3.col3,T4.col4
FROM
  (SELECT col1,@order1:=@order1+1 as i 
   FROM (SELECT col1 FROM `table` ORDER BY RAND() LIMIT 4) O1,(SELECT @order1:=0) initialize )T1
  INNER JOIN
  (SELECT col2,@order2:=@order2+1 as i 
   FROM (SELECT col2 FROM `table` ORDER BY RAND() LIMIT 4) O1,(SELECT @order2:=0) initialize )T2
  ON T1.i = T2.i
  INNER JOIN
  (SELECT col3,@order3:=@order3+1 as i 
   FROM (SELECT col3 FROM `table` ORDER BY RAND() LIMIT 4) O1,(SELECT @order3:=0) initialize )T3
  ON T1.i = T3.i
  INNER JOIN
  (SELECT col4,@order4:=@order4+1 as i 
   FROM (SELECT col4 FROM `table` ORDER BY RAND() LIMIT 4) O1,(SELECT @order4:=0) initialize )T4
  ON T1.i = T4.i

sqlfiddle shuffle columns vertically

答案 2 :(得分:1)

如果每个结果行必须独立,那么除了选择16个随机行(对于4x4结果表中的每个单元格一次),没有其他方法。

SELECT 
  (SELECT col1 FROM `table` ORDER BY RAND() LIMIT 1) AS col1,
  (SELECT col2 FROM `table` ORDER BY RAND() LIMIT 1) AS col2,
  (SELECT col3 FROM `table` ORDER BY RAND() LIMIT 1) AS col3,
  (SELECT col4 FROM `table` ORDER BY RAND() LIMIT 1) AS col4
FROM `table`
LIMIT 4

答案 3 :(得分:0)

这个会做但我猜我确定 表现得非常好:

select * from
    (select col1 from table order by rand()) as a, 
    (select col2 from table order by rand()) as b,
    (select col3 from table order by rand()) as c,
    (select col4 from table order by rand()) as d
order by rand()
limit 4;

它在所有4个表上进行交叉连接(给出n ^ 4行),然后获取它的前4行。

更新,因为OP询问了a/b/c/d

的用途

ab等只是(随机选择)4个子查询的别名,可以看作(临时)表名。 语法需要它们来引用子查询。在这个特定的例子中,它们是无用的,但MySQL(以及可能还有其他系统)需要它们。

在上面的语句中,列名称已经是唯一的,但考虑列名称不是唯一的情况,并且您希望对列执行某些操作,如下所示:

select concat(a.col1, ' ', c.col1), b.col2, d.col2 from
    (select col1 from table order by rand()) as a, 
    (select col2 from table order by rand()) as b,
    (select col1 from table order by rand()) as c,
    (select col2 from table order by rand()) as d
where b.col2 > d.col2
order by rand()
limit 4;

然后,这些别名ad 确实 需要区分,例如来自第1和第3子选择的col1

然而,@ PaulSpiegel的answer比我好,因为我错过了子查询中的limit 1