关于VB中使用access的Rnd产生随机数据的问题

vbman2003 2007-07-05 10:00:28
问这个问题的人蛮多,最近正好也在写一个小东西遇上了这个问题,在网上搜索了下没找到解决办法。最后在access版的老大们帮助下解决了,有兴趣的可以交流一下

SQL数据库有个newid函数,可以很方便的用SQL语句得到表中的随机数据。但access数据库没这么方便,虽然有个Rnd,可以通过“select top 10 * from tb order by rnd(id)”得到随机数据,可惜在VB中使用,产生的随机序列是一样的。

有人说在程序中加上Randomize初始化随机种子,那么这只说对了一半,在程序中简单的加上Randomize,是没作用的,道理很简单,Randomize不可能影响SQL语句中的rnd,那只不过是个字符串,SQL语句是放到jet中去执行的。

前些天在论坛上看到有人说用time,那么只用rnd(time)这样是不行的,rnd中必须要包含表中的一个字段(任意字段,当然是主键效果更好),测试下来,rnd(time+id)这样依然不行! 不过非常意外的是rnd(time-id)却成功了。为什么说意外,按我的理解,time在与数值做运算时,会转换成一个小于1的double,这样与ID(大于1的正值)做减运算的结果必然是一个负数,我们知道rnd如果用了负数种子,会产生相同的随机序列,这是文件加解密算法中常用到的方法,可在这儿却能得到正确的结果,到现在也没想通......

接下去,用rnd(time-id)继续测试你会发现,连续快速地查询下,会有问题,会出现二次或三次查询结果一样的问题。分析一下可以找到原因,rnd(number)中的number是个single,这样它会截断time-id这个运算结果double后面数字,这样快速查询时number这个值没改变,所以查询结果也没有改变

总结一下上面的测试,结论就是蔘access中用SQL语句产生随机数据时,rnd的种子必须是一个负的single,这样最后的结果就是:

......
Dim sql As String
Dim r As Single
Randomize
r = Rnd
sql = "select top 1 * from tb order by rnd(" & r & "-id)"
......


(或许你早就知道了,不过我自己弄出来了还是很高兴,所以散分,不要打击我 ^_^)
...全文
1693 25 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
e103e104 2010-02-25
  • 打赏
  • 举报
回复
成了,謝謝樓豬.








--------------------------------------
                傻瓜,我們都一樣.
                 愛上了你,我不保留.
wu3k 2008-05-23
  • 打赏
  • 举报
回复
我看楼主要失望了,在VB中Randomize (Timer())是可以的,不相信你可以测试一下
conn.Open strconn
Randomize (Timer())
strsql = "select * from tb_above Order By Rnd(ID)"
rs.Open strsql, conn
MsgBox rs.Fields("pcabove")
Set rs = Nothing
Set conn = Nothing
以上已经经过证实,每次msgbox的数据是随机变动的
ultrafrog 2007-07-07
  • 打赏
  • 举报
回复
我做asp的时候也用到过这个东西.可惜那个时候没有参透就急着用上了.现在算是知道原理了.

还有貌似VB或是VBScript有缓存导致rnd()失败.在ACCESS中建立查询这样的语句是成立的.
bejge1121 2007-07-07
  • 打赏
  • 举报
回复
备用~~~~
vbman2003 2007-07-07
  • 打赏
  • 举报
回复
我试过,在sql语句查询的时候,你只执行一条查询语句,只执行一次,所以只rnd出来一个数,这个时候你再排序也没用,因为每条数据的值都是一样的!
---------------------------
不很明白你的意思,你的意思是每次查询rnd用不同的负参数也不行?

VBAdvisor 2007-07-07
  • 打赏
  • 举报
回复
没试过。先Mark up,以后遇到再看看。
liyi830 2007-07-07
  • 打赏
  • 举报
回复
mark
acev 2007-07-06
  • 打赏
  • 举报
回复
考虑的挺透,支持一个。
  • 打赏
  • 举报
回复
嗯 负负相加还是负数~
vbman2003 2007-07-06
  • 打赏
  • 举报
回复
啊,钻了牛角尖了,想通了......
SQL语句每一次都在执行一个负的不同参数的rnd,所以每一次都会得到一个不同的随机序列
rnd(number)中的值,不管+-ID,只要每次执行SQL语句时,是不同的负值,就可以得到正确的随机结果。
mickorguo 2007-07-06
  • 打赏
  • 举报
回复
要不你在SQL SERVER中用NEWID()吧
mickorguo 2007-07-06
  • 打赏
  • 举报
回复
我试过,在sql语句查询的时候,你只执行一条查询语句,只执行一次,所以只rnd出来一个数,这个时候你再排序也没用,因为每条数据的值都是一样的!
yin9184 2007-07-06
  • 打赏
  • 举报
回复
mark
kenshu 2007-07-06
  • 打赏
  • 举报
回复
谢谢!
zzyong00 2007-07-06
  • 打赏
  • 举报
回复
收藏了
vbman2003 2007-07-06
  • 打赏
  • 举报
回复
是不是ACCESS中的RND函数与VB的中RND函数有不同呢?
在VB中,RND(负数)得到的相同的随机数,也许ACCESS中就不是这样了。
----------------------
access也是,rnd(number)的nember是负数会得到一个随机序列,不过这里这个负参数每次查询时不一样,所以每次查询就会生产一个新的随机序列
SQL语句是通过数据库引擎去执行的,不是在VB中执行,VB中的Randomize不会直接影响SQL语句中的rnd,所以每次查询,只有通过不同的负参数使access的rnd产生与前次不同的随机序列,我是这样理解的,大家可以讨论。
szjhxu 2007-07-06
  • 打赏
  • 举报
回复
是不是ACCESS中的RND函数与VB的中RND函数有不同呢?
在VB中,RND(负数)得到的相同的随机数,也许ACCESS中就不是这样了。
yangao 2007-07-05
  • 打赏
  • 举报
回复
学习
gebizhihu 2007-07-05
  • 打赏
  • 举报
回复
真的是好东西,谢谢分享~~~
yachong 2007-07-05
  • 打赏
  • 举报
回复
收藏备用:)
加载更多回复(5)

1,217

社区成员

发帖
与我相关
我的任务
社区描述
VB 数据库(包含打印,安装,报表)
社区管理员
  • 数据库(包含打印,安装,报表)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧