随机在A表里面取5条记录怎么取?不能重复
不能使用 ORDER BY RAND(),因为效率太差了

解决方案 »

  1.   

    随机生成5个ID,检查一下数据库中是不存在这个ID,没有接着生成,有的话就取出来做个取出标记
      

  2.   

    恩,后来我也是这么做,不过数据量大了效率也很低
    function GetRandRecord(){
    $arr = array();
    $row_num = $db->result_first("SELECT count(*) FROM a WHERE");
    while(true){
    $query1 = $db->query("SELECT floor(RAND() * (SELECT MAX(id) FROM a)+1)");
    if($row1 = $db->fetch_array_num($query1)){
    $query2 = $db->query("SELECT name FROM a WHERE id = '".$row1[0]."'");    
    if($row2 =  $db->fetch_array($query2)){
    if(!empty($row2['name'])){
    $arr[] = $row2['name'];            
    }        
    }    
    }
    $arr = array_unique($arr);
    if(count($arr) == 5 || count($arr) == $row_num){break;}

    return $arr;
    } 写了这么个函数来保存,发现效率还是很低
      

  3.   

    看下这个
    http://www.itlearner.com/article/4643
      

  4.   

    SELECT *   
    FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`))+(SELECT MIN(id) FROM `table`)) AS id) AS t2   
    WHERE t1.id >= t2.id   
    ORDER BY t1.id LIMIT 5;
    试了下,速度很快!
      

  5.   


    随机5个数然后 采用 union all 写5条连接. 这样速度快 还可以用到索引.
    如:select * from a where id = 10
       union all select * from a where id = 20 ......; 
      

  6.   

    union all的写5条和我写的那个循环5条应该没有差别吧?
      

  7.   

    另外for循环5条,可能有重复和空值,这个怎么解决
      

  8.   

    不要求纯粹随机的话可以仅仅采用随机偏移量的方式,例如你想取到最新入库的100条数据的随机5条,在php端$rand=rand(1,95),取到一个偏移量,然后取limit $rand,5,以此类推,然后如果想扩大范围的话,可以加一个量级,即$lev=rand(0,100),然后取limit ($rand+$lev*100),5,或者直接令rand的范围足够大也可以
      

  9.   

    这有啥难度?难道不是这样吗?1、取总记录$rs
    2、$rs转数组$rs,数组随机函数array_rand($rs,5)。
      

  10.   

    方法2(数据量非常大的时候)1、取所有记录ID,保存为数组$ids
    2、数组$ids序列化(json化,serialize($ids)),再保存成缓存文件ids.php
    3、用的时候file_get_contents 为字符串$ids,字符串转数组unserialize($ids)。
    4、随机数组。
      

  11.   

    给你看下我以前反的一个帖子,很早了http://topic.csdn.net/u/20070827/15/7b8b235b-66d8-4c93-aee9-fe8b58fa9d45.html
      

  12.   


    1000万条数据,就不必执着于是否真的从这1000万条随机了,又不是彩票。方法1:可以随机从0-100里取出一个数字3次,三次相乘得到一个数字n,第多少条,然后limit n,1。方法2:或者看看你的自增量id是多少位,是多少位,就分别随机0-9多少次。得到准确的ID,成功则返回,失败则再随机直到成功。
      

  13.   

    补充:方法一有误,应该是随机1-10 7次。7次结果相乘。或者7个随机0-9数字组成一个随机数n,然后sql:limit 1,n。
      

  14.   

    再来一个思路:
    1.生成并检测: 写一个函数生成随机ID,检测数据库中存在否并且过滤掉重复值.
                          将这些值放在一个数组中$a;
    2.取数据: 这个过程就最直接了,直接SQL写语句 
                   SELECT * FROM A WHERE ID IN($a[0],$a[1],$a[2],$a[3],$a[4])....
          这样直接取出5条随机记录.要说这个思路有些麻烦的地方,就是在第1点中,要检测存在.
    不过只是判断一下而非取数据应该会提升不少效率的
      

  15.   

    如果没有“一定要不连串的数据”规定的话好做。
    比如一共有1000条数据。
    $num = rand(0,996);
    $sql = "SELECT * FROM `my_table` limit " . $num. ",5";
    搞定!呵呵~
      

  16.   

    array_rand 这个打乱的是索引? 可以打乱值吗?
      

  17.   


    你这个查询可以不放在循环里面每次都做,
    $query1 = $db->query("SELECT floor(RAND() * (SELECT MAX(id) FROM a)+1)");
    另,16楼的方法就很好,和你的大体一样,但是用了<或>可以每次都得到一个结果
    另另,看你的id分布,
    如果id分布密集,用rand(1,max(id))生成〉5个(比如搞个10个)
    然后用 in (x1,x2)这样一次取出来, mysql对有索引的列上做in还是比较快的
    另另另,如果什么方法都不快,升级服务器降低需求,比如只取随机一个。。比如用假随机(楼上各种)
      

  18.   

    试下下面这个,可以消除filesort
    SELECT  * FROM    (         
        SELECT  @cnt := COUNT(*) + 1,                 
        @lim := 5         
        FROM   表名
    ) vars STRAIGHT_JOIN(
        SELECT  r.*,                 
        @lim := @lim - 1         
        FROM   表名 r         
        WHERE   (@cnt := @cnt - 1)                 
        AND RAND() < @lim / @cnt         
    ) i