MySQL快速从600K行中选择10个随机行

时间:2010-12-01 21:35:15

标签: mysql sql

如何最好地编写一个从总共600k中随机选择10行的查询?

28 个答案:

答案 0 :(得分:362)

一个很棒的文章处理几个案例,从简单到间隙,到有间隙的不均匀。

http://jan.kneschke.de/projects/mysql/order-by-rand/

对于大多数一般情况,以下是您的操作方法:

SELECT name
  FROM random AS r1 JOIN
       (SELECT CEIL(RAND() *
                     (SELECT MAX(id)
                        FROM random)) AS id)
        AS r2
 WHERE r1.id >= r2.id
 ORDER BY r1.id ASC
 LIMIT 1

这假设id的分布相等,并且id列表中可能存在间隙。有关更多高级示例,请参阅文章

答案 1 :(得分:313)

SELECT column FROM table
ORDER BY RAND()
LIMIT 10

不是有效的解决方案,但有效

答案 2 :(得分:18)

非常简单的单行查询。

SELECT * FROM Table_Name ORDER BY RAND() LIMIT 0,10;

答案 3 :(得分:17)

我正在使用慢速cpu 获得快速查询(大约0.5秒),在400K寄存器MySQL数据库非缓存2Gb大小中选择10个随机行。在这里查看我的代码:Fast selection of random rows in MySQL

<?php
$time= microtime_float();

$sql='SELECT COUNT(*) FROM pages';
$rquery= BD_Ejecutar($sql);
list($num_records)=mysql_fetch_row($rquery);
mysql_free_result($rquery);

$sql="SELECT id FROM pages WHERE RAND()*$num_records<20
   ORDER BY RAND() LIMIT 0,10";
$rquery= BD_Ejecutar($sql);
while(list($id)=mysql_fetch_row($rquery)){
    if($id_in) $id_in.=",$id";
    else $id_in="$id";
}
mysql_free_result($rquery);

$sql="SELECT id,url FROM pages WHERE id IN($id_in)";
$rquery= BD_Ejecutar($sql);
while(list($id,$url)=mysql_fetch_row($rquery)){
    logger("$id, $url",1);
}
mysql_free_result($rquery);

$time= microtime_float()-$time;

logger("num_records=$num_records",1);
logger("$id_in",1);
logger("Time elapsed: <b>$time segundos</b>",1);
?>

答案 4 :(得分:15)

具有卓越性能的简单查询(适用于差距):

SELECT * FROM tbl WHERE id IN 
    (SELECT id FROM (SELECT id FROM tbl ORDER BY RAND() LIMIT 10) t)

使用了两个嵌套子查询,因为MySQL在第一个中不支持LIMIT。

这很快,因为排序阶段仅使用索引ID列。

对于加权版:https://stackoverflow.com/a/41577458/893432

答案 5 :(得分:13)

来自书:

使用偏移选择随机行

另一种避免前面发现的问题的技术 替代方法是计算数据集中的行并随机返回 0到计数之间的数字。然后使用此数字作为偏移量 查询数据集时

<?php
$rand = "SELECT ROUND(RAND() * (SELECT COUNT(*) FROM Bugs))";
$offset = $pdo->query($rand)->fetch(PDO::FETCH_ASSOC);
$sql = "SELECT * FROM Bugs LIMIT 1 OFFSET :offset";
$stmt = $pdo->prepare($sql);
$stmt->execute( $offset );
$rand_bug = $stmt->fetch();

当您无法假设连续的键值时,请使用此解决方案 你需要确保每一行都有可能被选中。

答案 6 :(得分:7)

如何从表格中选择随机行:

从这里: Select random rows in MySQL

对“表扫描”的快速改进是使用索引来获取随机ID。

SELECT *
FROM random, (
        SELECT id AS sid
        FROM random
        ORDER BY RAND( )
        LIMIT 10
    ) tmp
WHERE random.id = tmp.sid;

答案 7 :(得分:6)

如果您的按键没有间隙并且它们都是数字,您可以计算随机数并选择这些线。但情况可能并非如此。

所以一个解决方案如下:

SELECT * FROM table WHERE key >= FLOOR(RAND()*MAX(id)) LIMIT 1

这基本上可以确保您在按键范围内获得一个随机数,然后选择下一个更好的随机数。 你必须这样做10次。

然而,这并不是随机的,因为您的密钥很可能不会均匀分布。

这真的是一个很大的问题,并不容易解决满足所有要求,如果你真的想要10个随机行,MySQL的rand()是你能得到的最好的。

然而,另一种解决方案是快速的,但在随机性方面也有一个折衷,但可能更适合你。在此处阅读:How can i optimize MySQL's ORDER BY RAND() function?

问题是你需要它是多么随机。

你能解释一下,我可以给你一个很好的解决方案。

例如,我合作过的公司有一个解决方案,他们需要极快的绝对随机性。他们最终使用随机值预先填充数据库,这些随机值经过降序选择,然后再次设置为不同的随机值。

如果你几乎没有更新,你也可以填充递增的ID,这样你就没有间隙,只能在选择之前计算随机密钥......这取决于用例!

答案 8 :(得分:3)

我使用了Riedsio发布的http://jan.kneschke.de/projects/mysql/order-by-rand/(我使用了返回一个或多个随机值的存储过程的情况):

   DROP TEMPORARY TABLE IF EXISTS rands;
      CREATE TEMPORARY TABLE rands ( rand_id INT );

    loop_me: LOOP
        IF cnt < 1 THEN
          LEAVE loop_me;
        END IF;

        INSERT INTO rands
           SELECT r1.id
             FROM random AS r1 JOIN
                  (SELECT (RAND() *
                                (SELECT MAX(id)
                                   FROM random)) AS id)
                   AS r2
            WHERE r1.id >= r2.id
            ORDER BY r1.id ASC
            LIMIT 1;

        SET cnt = cnt - 1;
      END LOOP loop_me;

在文章中,他通过维护表(使用触发器等等)来解决导致不是随机结果的ID中的间隙问题;请参阅文章); 我正在通过向表中添加另一列来填充问题,从1开始填充连续的数字( edit: 此列添加到由此创建的临时表中运行时的子查询,不会影响您的永久表):

   DROP TEMPORARY TABLE IF EXISTS rands;
      CREATE TEMPORARY TABLE rands ( rand_id INT );

    loop_me: LOOP
        IF cnt < 1 THEN
          LEAVE loop_me;
        END IF;

        SET @no_gaps_id := 0;

        INSERT INTO rands
           SELECT r1.id
             FROM (SELECT id, @no_gaps_id := @no_gaps_id + 1 AS no_gaps_id FROM random) AS r1 JOIN
                  (SELECT (RAND() *
                                (SELECT COUNT(*)
                                   FROM random)) AS id)
                   AS r2
            WHERE r1.no_gaps_id >= r2.id
            ORDER BY r1.no_gaps_id ASC
            LIMIT 1;

        SET cnt = cnt - 1;
      END LOOP loop_me;

在文章中我可以看到他竭尽全力优化代码;我不知道我的变化会影响表现,但对我来说效果很好。

答案 9 :(得分:3)

我需要一个查询来从一个相当大的表中返回大量随机行。这就是我提出的。首先获得最大记录ID:

SELECT MAX(id) FROM table_name;

然后将该值替换为:

SELECT * FROM table_name WHERE id > FLOOR(RAND() * max) LIMIT n;

其中max是表中的最大记录ID,n是结果集中所需的行数。假设记录id中没有间隙,尽管我怀疑它会影响结果(如果有的话)(虽然没有尝试过)。我还创建了这个存储过程更通用;传入表名和要返回的行数。我在Windows 2008,32GB,双3GHz E5450上运行MySQL 5.5.38,在具有17,361,264行的桌面上,它在〜。03秒/ ~11秒时相当一致,返回1,000,000行。 (时间来自MySQL Workbench 6.1;根据您的偏好,您也可以在第二个选择语句中使用CEIL而不是FLOOR)

DELIMITER $$

USE [schema name] $$

DROP PROCEDURE IF EXISTS `random_rows` $$

CREATE PROCEDURE `random_rows`(IN tab_name VARCHAR(64), IN num_rows INT)
BEGIN

SET @t = CONCAT('SET @max=(SELECT MAX(id) FROM ',tab_name,')');
PREPARE stmt FROM @t;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @t = CONCAT(
    'SELECT * FROM ',
    tab_name,
    ' WHERE id>FLOOR(RAND()*@max) LIMIT ',
    num_rows);

PREPARE stmt FROM @t;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
$$

然后

CALL [schema name].random_rows([table name], n);

答案 10 :(得分:2)

所有最佳答案都已发布(主要是那些引用链接http://jan.kneschke.de/projects/mysql/order-by-rand/)。

我想确定另一种加速可能性 - 缓存。想想你为什么需要获得随机行。您可能希望在网站上显示一些随机帖子或随机广告。如果你得到100 req / s,是否真的需要每个访问者获得随机行?通常将这些X随机行缓存1秒(甚至10秒)完全没问题。如果100个独立访问者在同一个1秒内获得相同的随机帖子并不重要,因为下一秒另外100个访问者将获得不同的帖子。

使用此缓存时,您还可以使用一些较慢的解决方案来获取随机数据,因为无论您的req / s是什么,它都将每秒从MySQL获取一次。

答案 11 :(得分:2)

我改进了@Riedsio的答案。这是我在一个大的,均匀分布的表上有间隙时可以找到的最有效的查询(在从具有> 2.6B行的表中获取1000个随机行时进行测试)。

(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max := (SELECT MAX(id) FROM table)) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1)

让我解开正在发生的事情。

  1. @max := (SELECT MAX(id) FROM table)
    • 我正在计算并保存最大值。对于非常大的表,每次需要行时计算MAX(id)会有轻微的开销
  2. SELECT FLOOR(rand() * @max) + 1 as rand)
    • 获取随机ID
  3. SELECT id FROM table INNER JOIN (...) on id > rand LIMIT 1
    • 这填补了空白。基本上,如果您在间隙中随机选择一个数字,它将只选择下一个ID。假设间隙均匀分布,这应该不是问题。
  4. 执行联合可帮助您将所有内容都放入1个查询中,这样您就可以避免执行多个查询。它还可以节省计算MAX(id)的开销。根据您的应用程序,这可能很重要或很少。

    请注意,这只会获取ID并以随机顺序获取它们。如果你想做更高级的事情,我建议你这样做:

    SELECT t.id, t.name -- etc, etc
    FROM table t
    INNER JOIN (
        (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max := (SELECT MAX(id) FROM table)) + 1 as rand) r on id > rand LIMIT 1) UNION
        (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
        (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
        (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
        (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
        (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
        (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
        (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
        (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
        (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1)
    ) x ON x.id = t.id
    ORDER BY t.id
    

答案 12 :(得分:2)

这是一个可能对许多人有帮助的游戏改变者;

我有一个包含200k行的表,包含顺序ID&#39> ,我需要选择 N 随机行,所以我选择生成基于的随机值表中最大的ID,我创建了这个脚本来找出哪个是最快的操作:

logTime();
query("SELECT COUNT(id) FROM tbl");
logTime();
query("SELECT MAX(id) FROM tbl");
logTime();
query("SELECT id FROM tbl ORDER BY id DESC LIMIT 1");
logTime();

结果是:

  • 数:36.8418693542479 ms
  • Max:0.241041183472 ms
  • 订单:0.216960906982 ms

根据此结果,订单desc是获得最大ID的最快操作,
以下是我对这个问题的回答:

SELECT GROUP_CONCAT(n SEPARATOR ',') g FROM (
    SELECT FLOOR(RAND() * (
        SELECT id FROM tbl ORDER BY id DESC LIMIT 1
    )) n FROM tbl LIMIT 10) a

...
SELECT * FROM tbl WHERE id IN ($result);

仅供参考:要从200k表中获取10个随机行,我需要1.78 ms (包括php端的所有操作)

答案 13 :(得分:1)

另一个简单的解决方案是对行进行排名并随机获取其中一行,使用此解决方案,您不需要拥有任何“ID”标记。基于表的列。

SELECT d.* FROM (
SELECT  t.*,  @rownum := @rownum + 1 AS rank
FROM mytable AS t,
    (SELECT @rownum := 0) AS r,
    (SELECT @cnt := (SELECT RAND() * (SELECT COUNT(*) FROM mytable))) AS n
) d WHERE rank >= @cnt LIMIT 10;

您可以根据需要更改限制值,以根据需要访问任意数量的行,但这些行大多数是连续值。

但是,如果您不想要连续的随机值,那么您可以获取更大的样本并从中随机选择。类似......

SELECT * FROM (
SELECT d.* FROM (
    SELECT  c.*,  @rownum := @rownum + 1 AS rank
    FROM buildbrain.`commits` AS c,
        (SELECT @rownum := 0) AS r,
        (SELECT @cnt := (SELECT RAND() * (SELECT COUNT(*) FROM buildbrain.`commits`))) AS rnd
) d 
WHERE rank >= @cnt LIMIT 10000 
) t ORDER BY RAND() LIMIT 10;

答案 14 :(得分:1)

如果您只有一个读取请求

将@redsio的答案与临时表(600K不是那么多)结合起来:

DROP TEMPORARY TABLE IF EXISTS tmp_randorder;
CREATE TABLE tmp_randorder (id int(11) not null auto_increment primary key, data_id int(11));
INSERT INTO tmp_randorder (data_id) select id from datatable;

然后拿一个版本的@redsios答案:

SELECT dt.*
FROM
       (SELECT (RAND() *
                     (SELECT MAX(id)
                        FROM tmp_randorder)) AS id)
        AS rnd
 INNER JOIN tmp_randorder rndo on rndo.id between rnd.id - 10 and rnd.id + 10
 INNER JOIN datatable AS dt on dt.id = rndo.data_id
 ORDER BY abs(rndo.id - rnd.id)
 LIMIT 1;

如果桌子很大,你可以在第一部分筛选:

INSERT INTO tmp_randorder (data_id) select id from datatable where rand() < 0.01;

如果您有许多读取请求

  1. 版本:您可以保持表tmp_randorder持久,将其称为datatable_idlist。以特定间隔(日,小时)重新创建该表,因为它也会出现漏洞。如果你的桌子变得很大,你也可以补充漏洞

    选择整个l.data_id 来自datatable_idlist l 在dt.id = l.data_id上左连接数据表dt 其中dt.id为null;

  2. 版本:直接在数据表或持久性额外表datatable_sortorder中为数据集提供random_sortorder列。索引该列。在您的应用程序中生成随机值(我将其称为$rand)。

    select l.*
    from datatable l 
    order by abs(random_sortorder - $rand) desc 
    limit 1;
    
  3. 此解决方案区分边缘行&#39;具有最高和最低的random_sortorder,因此每隔一段时间(每天一次)重新排列它们。

答案 15 :(得分:1)

如果有自动生成的id,我觉得非常好的一种方法是使用模运算符'%'。例如,如果您需要10,000个随机记录70,000,您可以通过说您需要每7行中有1个来简化此操作。这可以在此查询中简化:

SELECT * FROM 
    table 
WHERE 
    id % 
    FLOOR(
        (SELECT count(1) FROM table) 
        / 10000
    ) = 0;

如果将目标行除以总可用的结果不是整数,那么您将有一些额外的行,因此您应该添加一个LIMIT子句来帮助您修剪结果集,如下所示:

SELECT * FROM 
    table 
WHERE 
    id % 
    FLOOR(
        (SELECT count(1) FROM table) 
        / 10000
    ) = 0
LIMIT 10000;

这确实需要完整扫描,但它比ORDER BY RAND更快,在我看来比这个线程中提到的其他选项更容易理解。此外,如果写入数据库的系统批量创建行集,则可能无法获得如此随机的结果。

答案 16 :(得分:1)

如果你想要一个随机记录(无论ids之间是否有噱头):

PREPARE stmt FROM 'SELECT * FROM `table_name` LIMIT 1 OFFSET ?';
SET @count = (SELECT
        FLOOR(RAND() * COUNT(*))
    FROM `table_name`);

EXECUTE stmt USING @count;

来源:https://www.warpconduit.net/2011/03/23/selecting-a-random-record-using-mysql-benchmark-results/#comment-1266

答案 17 :(得分:1)

这是超快的,即使有差距,也是100%随机的。

  1. 计算x可用的行数SELECT COUNT(*) as rows FROM TABLE
  2. 从0到a_1,a_2,...,a_10之间选取10个不同的随机数x
  3. 像这样查询行:SELECT * FROM TABLE LIMIT 1 offset a_i for i = 1,...,10

我在 Bill Karwin SQL Antipatterns 一书中发现了这种黑客攻击。

答案 18 :(得分:1)

我知道这不是您想要的,但我会给您的答案是我在 small website 的生产中使用的。

根据您访问随机值的次数,不值得使用MySQL,因为您将无法缓存答案。我们有一个按钮可以访问随机页面,如果用户愿意,可以每分钟点击几次。这会导致大量的 MySQL 使用,至少对我来说,MySQL 是最大的优化问题。

我会采用另一种方法,您可以将答案存储在缓存中。对您的 MySQL 进行一次调用:

SELECT min(id) as min, max(id) as max FROM your_table

使用您的最小和最大 ID,您可以在您的服务器中计算一个随机数。在蟒蛇中:

random.randint(min, max)

然后,使用您的随机数,您可以在表中获得一个随机 ID:

SELECT * 
FROM your_table 
WHERE id >= %s 
ORDER BY id ASC 
LIMIT 1

在这种方法中,您对数据库进行了两次调用,但您可以将它们缓存起来并且长时间不访问数据库,从而提高了性能。请注意,如果您的桌子上有洞,这不是随机的。多于 1 行很容易,因为您可以使用 python 创建 Id 并对每一行执行一个请求,但由于它们被缓存,所以没关系。

答案 19 :(得分:0)

我已经仔细查看了所有答案,但我认为没有人提到过这种可能性,而且我不确定为什么。

如果您希望以最小的成本获得最大的简便性和速度,那么对我来说,在数据库中针对每一行存储一个随机数似乎是有意义的。只需创建一个额外的列random_number,并将其默认设置为RAND()。在此列上创建索引。

然后,当您要检索行时,会在代码中生成一个随机数(PHP,Perl等)并将其与列进行比较。

SELECT FROM tbl WHERE random_number >= :random LIMIT 1

我想虽然单行非常整洁,但对于10行(如OP),您必须将其分别命名十次(或想出一个巧妙的调整方法,使我立即逃脱)

答案 20 :(得分:0)

以下内容应快速,公正且独立于id列。 但是,它不能保证返回的行数将与请求的行数匹配。

SELECT *
FROM t
WHERE RAND() < (SELECT 10 / COUNT(*) FROM t)

说明:假设您要从100中选择10行,那么每行都有1/10的被选择概率,这可以通过WHERE RAND() < 0.1实现。这种方法不能保证10行。但是如果查询运行了足够多次,则每次执行的平均行数将约为10,并且表中的每一行将被均匀选择。

答案 21 :(得分:0)

您可以轻松地使用带有限制的随机偏移量

PREPARE stm from 'select * from table limit 10 offset ?';
SET @total = (select count(*) from table);
SET @_offset = FLOOR(RAND() * @total);
EXECUTE stm using @_offset;

您还可以像这样应用where子句

PREPARE stm from 'select * from table where available=true limit 10 offset ?';
SET @total = (select count(*) from table where available=true);
SET @_offset = FLOOR(RAND() * @total);
EXECUTE stm using @_offset;

对600,000行(700MB)的表查询执行进行了测试,使用了约0.016秒的HDD驱动器。

EDIT :偏移量可能接近表末尾的值,这将导致select语句返回较少的行(或可能只有1行),为避免这种情况,我们可以检查一下声明后再次offset

SET @rows_count = 10;
PREPARE stm from "select * from table where available=true limit ? offset ?";
SET @total = (select count(*) from table where available=true);
SET @_offset = FLOOR(RAND() * @total);
SET @_offset = (SELECT IF(@total-@_offset<@rows_count,@_offset-@rows_count,@_offset));
SET @_offset = (SELECT IF(@_offset<0,0,@_offset));
EXECUTE stm using @rows_count,@_offset;

答案 22 :(得分:0)

我认为这是一种简单但又更快的方法,与上面的一些答案相比,我在实时服务器上对其进行了测试,并且速度更快。

 SELECT * FROM `table_name` WHERE id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `table_name` ) ORDER BY id LIMIT 30; 

//对130行的表进行0.0014秒的操作

SELECT * FROM `table_name` WHERE 1 ORDER BY RAND() LIMIT 30

//对130行的表进行0.0042秒的操作

 SELECT name
FROM random AS r1 JOIN
   (SELECT CEIL(RAND() *
                 (SELECT MAX(id)
                    FROM random)) AS id)
    AS r2
WHERE r1.id >= r2.id
ORDER BY r1.id ASC
LIMIT 30

//对130行的表进行0.0040秒的操作

答案 23 :(得分:0)

SELECT
  * 
FROM
  table_with_600k_rows
WHERE
  RAND( ) 
ORDER BY
  id DESC 
LIMIT 30;

id是主键,按id排序, EXPLAIN table_with_600k_rows,发现该行没有扫描整个表

答案 24 :(得分:-1)

我使用此查询:

select floor(RAND() * (SELECT MAX(key) FROM table)) from table limit 10

查询时间:0.016秒

答案 25 :(得分:-2)

使用以下简单查询从表中获取随机数据。

SELECT user_firstname ,
COUNT(DISTINCT usr_fk_id) cnt
FROM userdetails 
GROUP BY usr_fk_id 
ORDER BY cnt ASC  
LIMIT 10

答案 26 :(得分:-2)

我就是这样做的:

select * 
from table_with_600k_rows
where rand() < 10/600000
limit 10

我喜欢它,因为它不需要其他表,编写起来很简单,并且执行起来非常快。

答案 27 :(得分:-4)

我想这是最好的方式..

SELECT id, id * RAND( ) AS random_no, first_name, last_name
FROM user
ORDER BY random_no