要求:
1、每次抽样出的记录基本都不一样,即随机抽取
2、最好不要修改原有表的结构
3、效率要好

解决方案 »

  1.   

    难点就是SQL语句太实在,无法使用随机的概念。
      

  2.   

    MS SQLServer中使用 RAND
    RAND 函数计算 0 到 1 之间的随机浮点数,而且可选择以 tinyint、int 或 smallint 值作为要计算的随机数的起始点。下面的示例计算两个随机数。第一个 RAND() 函数让 Microsoft® SQL Server™ 选取种子值,第二个 RAND() 函数使用值 3 作为起始位置。SELECT RAND(), RAND(3)RAND 函数是伪随机的数字生成器,它用与 C 运行时库 rand 函数类似的方法进行操作。如果没有提供种子值,系统将生成它自己的不定种子值。如果用种子值调用 RAND,则必须使用不定的种子值来生成随机数。如果用同一种子值多次调用 RAND,它将返回相同的生成值。下面的脚本中,对 RAND 的调用都返回相同的值,这是因为它们都使用了相同的种子值:SELECT RAND(159784)
    SELECT RAND(159784)
    SELECT RAND(159784)通常用 RAND 生成随机数的方法是,用相对不定的某个值作为种子值,例如累加 GETDATE 的几个部分:SELECT RAND( (DATEPART(mm, GETDATE()) * 100000 )
               + (DATEPART(ss, GETDATE()) * 1000 )
               + DATEPART(ms, GETDATE()) )使用基于 GETDATE 的算法生成种子值时,如果在算法中所用的最小 datepart 的时间间隔内多次调用 RAND,RAND 仍会生成重复值。如果对 RAND 的调用包括在单个批处理中,尤其可能出现这种情况。在单个批处理中对 RAND 的多次调用可在同一毫秒(DATEPART 的最小增量)内执行。这种情况下,请用基于除时间之外的值以生成种子值。
      

  3.   

    用distince查独一无二的
    再用top一下如何?
    比如:
    select  top 1000 * from 
    (select distinct(字段名) from 表名)aa
      

  4.   

    Select中使用随机数
    下面是用当前日期作种子,这样可以保证第次都有不同的值
    但要完成抽样,好象还是比较困难,
    这是作取随机数据的函数,但愿能帮的上你
    SELECT RAND( (DATEPART(mm, GETDATE()) * 100000 )
               + (DATEPART(ss, GETDATE()) * 1000 )
               + DATEPART(ms, GETDATE()) )
      

  5.   

    RAND
    返回 0 到1 之间的随机float 值。语法
    RAND ( [ seed ] ) 参数
    seed是给出种子值或起始值的整型表达式(tinyint、smallint 或 int)。返回类型
    float注释
    在单个查询中反复调用 RAND() 将产生相同的值。示例
    下例产生 4 个通过 RAND 函数产生的不同的随机值。DECLARE @counter smallint
    SET @counter = 1
    WHILE @counter < 5
       BEGIN
          SELECT RAND(@counter) Random_Number
          SET NOCOUNT ON
          SET @counter = @counter + 1
          SET NOCOUNT OFF
       END
    GO下面是结果集:Random_Number                                         
    ------------------- 
    0.71359199321292355(1 row(s) affected)Random_Number                                         
    ------------------- 
    0.7136106261841817(1 row(s) affected)Random_Number                                         
    ------------------- 
    0.71362925915543995(1 row(s) affected)Random_Number                                         
    ------------------- 
    0.7136478921266981(1 row(s) affected)
      

  6.   

    除了你在数据库中增加一列作为序号外,你还可以先建立一个cursor,取出数据库里面所有的记录数。这样数据库会默认一个顺序(可能是物理的),再根据随机函数取出你所需要的记录数目。
    /*************************************/
    /*1、MY TOOL:                        */
    /*2、Delphi,Oracle,Sybase,C++/C      */
    /*3、PROJECT:                        */
    /*3、Boss                            */
    /*4、为了五星的目标希望你早点结贴      */
    /*************************************/
      

  7.   

    你可以用随机数产生一个a[1..1000]of integer数祖存放序号的,当然随机数范围是(min) id 到(max)id,然后对应的就可以取出1000条随机纪录。细节自己想吧...
      

  8.   

    可以使用存储过程采用游标的那一种方法呀!
    /*************************************/
    /*1、MY TOOL:                        */
    /*2、Delphi,Oracle,Sybase,C++/C      */
    /*3、PROJECT:                        */
    /*3、Boss                            */
    /*4、为了五星的目标希望你早点结贴      */
    /*************************************/
      

  9.   

    强调一下:我是想从20万条记录的表中中随机抽取1000条记录,不是用SQL取随机数。
    不用CURSOR,可以实现吗?
      

  10.   

    能否利用SQL本身的数据乱序来实现呢?
      

  11.   

    1 建立一个20万的数组(集合)A,作为ID的取值范围。
    2 随机抽取1条。将它的ID从数组A中删除。
    3 循环1000次。
      

  12.   

    1 建立一个20万的数组(集合)A,作为ID的取值范围。
    2 随机抽取1条。将它的ID从数组A中删除。
    3 循环1000次。
      

  13.   

    不用SQL取数会死机的。哈哈,循环一千次怎么可能不死。客户机和服务器死一块了
    可以用客户机先生成一个随机数组呀,然后用SQL语句的In把数组元素包进来,这样一次性就抽出了1000条随机记录
      

  14.   

    楼主,估计你要问CSDN上五颗星的高手了,可惜好像我还没见到那样的主。
    帮你问了我们公司的哥哥,只有我说的上面两种方式可以得到你说的结果。
    至于有人说得利用数据库本身存放的乱序也不行,因为要是你对某个页面没有删除、插入操作的话,用类似top的东西取出来的数据还是不能达到随机的效果。
    在上面说得两种方法中,建议使用cursor,毕竟第一中的开销太大。
    /*************************************/
    /*1、MY TOOL:                        */
    /*2、Delphi,Oracle,Sybase,C++/C      */
    /*3、PROJECT:                        */
    /*3、Boss                            */
    /*4、为了五星的目标希望你早点结贴    */
    /*************************************/
      

  15.   

    只能用cursor  然后产生随机数,在自增自段中取
    但是这样会出现重复的,然后用union连接起来,
    解决重复的办法把那个随机数的范围调大一点,然后mod 200000这样的话出现
    重复的机会很小
      

  16.   

    随机抽取1000条使用游标是可以很容易的实现但是如果不用SQL和Cursor的真的会造成很大的负担的,无论是网络还是计算机资源!建议使用Cursor来实现顺便问一下,你的微软字典问题解决了吗?我先在休假结束好爽的假期,过后就是是无边的。。
      

  17.   

    我有办法拉, 你在查询分析器中, 创建一个游标,把20万记录分成1000段
    然后每段都是20个这是个概念,其实不用分段,然后循环1000次
    每次产生1-20的随机数,每次在前一次基础上加起来在判断Id是否等于当前的随机数,把他select 出来用union连接起来
    产生1.20的随机数语句为
    select cast(rand()*100 as int)
      

  18.   

    /* try this one */
    select top 1000 yourfieldlist,rand() as a
    from table1
    order by a
      

  19.   

    你的在sybase中怎么执行不了?
    /*************************************/
    /*1、MY TOOL:                        */
    /*2、Delphi,Oracle,Sybase,C++/C      */
    /*3、PROJECT:                        */
    /*3、Boss                            */
    /*4、为了五星的目标希望你早点结贴    */
    /*************************************/
      

  20.   

    参考一下
    procedure TrdmUserStudy.UserExam(const vUserID,vSubject,vExamType: WideString; var vQuestion ,vAnswer: OleVariant);
    var
      UserPos : String;
      UserCellPos : String;
      QesTotal , i , len , j , MoveDis : Integer;
      arrayQes , arrayAns : Variant;
      QesBag : TStringList;
    const
      QesAmount : Integer = 10;
    begin
      if vExamType = 'etUnit' then //单元测试
      begin
        //查找用户进程
        qryMain.Close;
        qryMain.SQL.Clear;
        qryMain.SQL.Add('SELECT cellNumber FROM userCourse');
        qryMain.SQL.Add('WHERE username = :pUserID');
        qryMain.SQL.Add('AND subject = :pSubject');
        qryMain.Parameters.ParamValues['pUserID'] := vUserID;
        qryMain.Parameters.ParamValues['pSubject'] := vSubject;
        if qryMain.Prepared = False then
        begin
          qryMain.Prepared := True;
        end;
        qryMain.Open;
        UserPos := Trim(qryMain.FieldByName('cellNumber').AsString);
        //查找课件所属单元
        qryMain.Close;
        qryMain.SQL.Clear;
        qryMain.SQL.Add('SELECT cellNumber FROM courseware');
        qryMain.SQL.Add('WHERE CoursewareNumber = :pCWN');
        qryMain.Parameters.ParamValues['pCWN'] := UserPos;
        if qryMain.Prepared = False then
        begin
          qryMain.Prepared := True;
        end;
        qryMain.Open;
        UserCellPos := Trim(qryMain.FieldByName('cellNumber').AsString);
        //读入考题
        qryMain.Close;
        qryMain.SQL.Clear;
        qryMain.SQL.Add('SELECT problemNumber,problemContent,answerContent FROM unitProblemStoreroom');
        qryMain.SQL.Add('WHERE subject = :pSubject');
        qryMain.SQL.Add('AND cellNumber = :pCWN');
        qryMain.Parameters.ParamValues['pSubject'] := vSubject;
        qryMain.Parameters.ParamValues['pCWN'] := UserCellPos;
        if qryMain.Prepared = False then
        begin
          qryMain.Prepared := True;
        end;
        qryMain.Open;    //取得符合条件全部题目
        QesTotal := qryMain.RecordCount;  //符合条件题目数量
        arrayQes := VarArrayCreate([0,QesAmount -1],varString);
        arrayAns := VarArrayCreate([0,QesAmount -1],varString);
        QesBag := TStringList.Create;
        for i := 0 to QesTotal-1 do   //题目编号读入缓冲区
        begin
          QesBag.Add(qryMain.FieldByName('problemNumber').AsString);
          qryMain.Next;
        end;
        qryMain.Close;
        qryMain.SQL.Clear;
        qryMain.SQL.Add('SELECT problemContent,answerContent FROM unitProblemStoreroom');
        qryMain.SQL.Add('WHERE problemNumber = :pCWN');
        Randomize;
        for i := 0 to QesAmount - 1 do
        begin
           qryMain.Close;
           len := QesBag.Count;
           j := Random(len);
           qryMain.Parameters.ParamValues['pCWN'] := QesBag[j]; //使用题目编号查找题目
           qryMain.Open;
           arrayQes[i] := qryMain.FieldByName('problemContent').AsString;
           arrayAns[i] := qryMain.FieldByName('AnswerContent').AsString;
           QesBag.Delete(i);
           qryMain.Close;
        end;
        QesBag.Free;
        //返回题目和答案
        vQuestion :=  arrayQes;
        vAnswer :=  arrayAns;
      end
      else if vExamType = 'etTerm' then  //全面测试
      begin
        //取得该科目所有单元编号
        qryMain.Close;
        qryMain.SQL.Clear;
        qryMain.SQL.Add('SELECT DISTINCT cellNumber FROM unitProblemStoreroom');
        qryMain.SQL.Add('WHERE subject = :pSubject');
        if qryMain.Prepared = False then
        begin
          qryMain.Prepared := True;
        end;
        qryMain.Open;
        QesBag := TStringList.Create;
        len := qryMain.RecordCount;
        for i := 0 to len - 1 do   //将单元编号装入缓冲
        begin
          QesBag.Add(qryMain.FieldByName('cellNumber').AsString);
          qryMain.Next;
        end;
        Randomize;
        arrayQes := VarArrayCreate([0,QesAmount -1],varString);
        arrayAns := VarArrayCreate([0,QesAmount -1],varString);
        for j := 0 to QesAmount - 1 do
        begin
          //查找随机单元题目
          qryMain.Close;
          qryMain.SQL.Clear;
          qryMain.SQL.Add('SELECT problemContent,answerContent FROM unitProblemStoreroom');
          qryMain.SQL.Add('WHERE subject = :pSubject');
          qryMain.SQL.Add('AND cellNumber = :pCWN');
          qryMain.Parameters.ParamValues['pSubject'] := vSubject;
          qryMain.Parameters.ParamValues['pCWN'] := QesBag[Random(len)];
          if qryMain.Prepared = False then
          begin
            qryMain.Prepared := True;
          end;
          qryMain.Open;
          QesTotal := qryMain.RecordCount;
          MoveDis := Random(QesTotal);  //随机移动指针
          qryMain.MoveBy(MoveDis);
          arrayQes[j] := qryMain.FieldByName('problemContent').AsString;
          arrayAns[j] := qryMain.FieldByName('AnswerContent').AsString;
        end;
        QesBag.Free;
        //返回题目和答案
        vQuestion :=  arrayQes;
        vAnswer :=  arrayAns;
      end;
    end;
      

  21.   

    如果SQL Server本身不提供該功能,我覺得只有和記錄號聯係起來,因爲即便有自增字段,但自增字段可能不是連續值,即不能代替記錄號,如果在Database Server中處理就要用Cursou了,如果在Delphi中處理就比較容易,Delphi已經為我們提供了RecNO,不過要消耗很多資源。
      

  22.   

    解释一下:1 建立一个20万的数组(集合)A,作为ID的取值范围。
    2 随机抽取1条。将它的ID从数组A中删除。
    3 循环1000次。以上操作不在数据库中执行,只是随机得到一个数字序列,包含了20万内的1000个随机 ID 号。全部操作都在内存中执行,在PII450机器上运行应该不会超过10秒钟。
      

  23.   

    1 可以假设该集合序列ID号为{1,2,3,...,200000}
    2 整型数组 R(1000)
    3 循环 
       for i=1 to 10000
         Do 
           flag=true
           R(i)=Rand()*200000    //Rand()为[0,1]随机数发生器
           for j=1 to i
             if R(i)=R(j) then  flag=false
           next j
         Until flag=true
       next i
      

  24.   

    select top 1000 * from TableName order by NewId()
    结贴给分!!!!
      

  25.   

    falaly的方法非常好,伴水的方法也不错。
    同时感谢大家的参与。某些方法是不太可行的,因为我可能会从数据表中抽取符合条件的记录,然后再抽样(怪我没讲清楚)。
    再次感谢,晚上结贴。
      

  26.   

    /*
    to chechy:
    falaly的方法,唯一的缺点在于newid()生成的GUID是有规律的
    ....
    E721D21F-7C7F-11D6-B538-005004BB9ED6
    E721D21F-7C7F-11D6-B538-005004BB9ED6
    E721D221-7C7F-11D6-B538-005004BB9ED6
    E721D222-7C7F-11D6-B538-005004BB9ED6
    E721D223-7C7F-11D6-B538-005004BB9ED6
    ....
    因此,1000个随机数据,是否很随机,不敢断言
    请你多测试测试看看
    */select top 1000 id
    from table1
    order by rand(id / (datepart(dd, getdate()) + 
      datepart(hh, getdate()) + 
      datepart(n, getdate()) +
      datepart(s, getdate()) +
      datepart(ms, getdate())))/* 其实思路都是一样的 */
      

  27.   

    呵呵,使用伴水的方法:
    select top 100 *,rand() as a
    from ypbm
    order by a
    得到的结果居然是表中的前100条记录,不知道我用对没有,我的表有一个PRIMARY KEY的?
    如果表中有一个标识字段的话,使用以下的方法可以不使用游标
    use test
    declare @count int,@random int ,@loop int
    select @count=count(*) from zg
    set @loop=1
    while @loop<=100 
    begin
     select @random=convert(int,rand(@loop*10000)*@count)
     if @random<=0 
     select @random=convert(int,rand(@loop*100)*@count)
     select * from zg where 编码 in (@random)
     select @loop=@loop+1
    -- print @random
    end