要求:
1、每次抽样出的记录基本都不一样,即随机抽取
2、最好不要修改原有表的结构
3、效率要好
1、每次抽样出的记录基本都不一样,即随机抽取
2、最好不要修改原有表的结构
3、效率要好
解决方案 »
- TImage的画布问题
- 谁有海康4000hc的卡的网络开发包的delphi的demo
- 如何用一个TIMER检测当前鼠标是否还在form范围内
- 欢迎各位赏脸^_^
- 问一个关于登陆另一台电脑的问题(WnetAddConnection2函数)?
- iphelper技术
- intraweb使用模块的问题
- 很菜的问题,如何将memo中的字符存入table,存入的字段长度为255,存入字符长度不超过255(我计算过了),为何会出现错误信息:List inde
- 这样为什么不行????
- 在Tadoquery中使用 update mytable set name='b' where name='a' 语句是否有问题?
- ReportBuilder问题
- 高分解决大难题!(200)
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 的最小增量)内执行。这种情况下,请用基于除时间之外的值以生成种子值。
再用top一下如何?
比如:
select top 1000 * from
(select distinct(字段名) from 表名)aa
下面是用当前日期作种子,这样可以保证第次都有不同的值
但要完成抽样,好象还是比较困难,
这是作取随机数据的函数,但愿能帮的上你
SELECT RAND( (DATEPART(mm, GETDATE()) * 100000 )
+ (DATEPART(ss, GETDATE()) * 1000 )
+ DATEPART(ms, GETDATE()) )
返回 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)
/*************************************/
/*1、MY TOOL: */
/*2、Delphi,Oracle,Sybase,C++/C */
/*3、PROJECT: */
/*3、Boss */
/*4、为了五星的目标希望你早点结贴 */
/*************************************/
/*************************************/
/*1、MY TOOL: */
/*2、Delphi,Oracle,Sybase,C++/C */
/*3、PROJECT: */
/*3、Boss */
/*4、为了五星的目标希望你早点结贴 */
/*************************************/
不用CURSOR,可以实现吗?
2 随机抽取1条。将它的ID从数组A中删除。
3 循环1000次。
2 随机抽取1条。将它的ID从数组A中删除。
3 循环1000次。
可以用客户机先生成一个随机数组呀,然后用SQL语句的In把数组元素包进来,这样一次性就抽出了1000条随机记录
帮你问了我们公司的哥哥,只有我说的上面两种方式可以得到你说的结果。
至于有人说得利用数据库本身存放的乱序也不行,因为要是你对某个页面没有删除、插入操作的话,用类似top的东西取出来的数据还是不能达到随机的效果。
在上面说得两种方法中,建议使用cursor,毕竟第一中的开销太大。
/*************************************/
/*1、MY TOOL: */
/*2、Delphi,Oracle,Sybase,C++/C */
/*3、PROJECT: */
/*3、Boss */
/*4、为了五星的目标希望你早点结贴 */
/*************************************/
但是这样会出现重复的,然后用union连接起来,
解决重复的办法把那个随机数的范围调大一点,然后mod 200000这样的话出现
重复的机会很小
然后每段都是20个这是个概念,其实不用分段,然后循环1000次
每次产生1-20的随机数,每次在前一次基础上加起来在判断Id是否等于当前的随机数,把他select 出来用union连接起来
产生1.20的随机数语句为
select cast(rand()*100 as int)
select top 1000 yourfieldlist,rand() as a
from table1
order by a
/*************************************/
/*1、MY TOOL: */
/*2、Delphi,Oracle,Sybase,C++/C */
/*3、PROJECT: */
/*3、Boss */
/*4、为了五星的目标希望你早点结贴 */
/*************************************/
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;
2 随机抽取1条。将它的ID从数组A中删除。
3 循环1000次。以上操作不在数据库中执行,只是随机得到一个数字序列,包含了20万内的1000个随机 ID 号。全部操作都在内存中执行,在PII450机器上运行应该不会超过10秒钟。
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
结贴给分!!!!
同时感谢大家的参与。某些方法是不太可行的,因为我可能会从数据表中抽取符合条件的记录,然后再抽样(怪我没讲清楚)。
再次感谢,晚上结贴。
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())))/* 其实思路都是一样的 */
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