VB中,从表中随机产生多条不重复的记录

时间:2021-06-10 00:48:40
Dim txtsql11 As String
Adodc1.CommandType = adCmdText
txtsql11 = "select * from " & Trim(Combo11.Text) & "试题 where 题型='" & Trim(Combo1.Text) & "'"
Adodc1.RecordSource = txtsql11
Adodc1.Refresh
If Adodc1.Recordset.RecordCount >= 1 Then
For i = 1 To Val(Trim(Text9.Text))  //text9是总共产生多少条不重复的记录数
Adodc1.Recordset.MoveFirst
Randomize
 n = Int(Rnd() * (Adodc1.Recordset.RecordCount + 1)) 
 For j = 1 To n - 1                   //此循环是为了将指针指向随机产生的第n条记录
 Adodc1.Recordset.MoveNext
 Next j
 If Adodc1.Recordset("状态") = " 1" Then //将表中的状态字段值改为1,说明已选中,不添加到word中,退出for循环       
 Exit For
 Else
.Content.InsertAfter (i & "、" & Adodc1.Recordset("题目")) & vbCr //将表中的题目字段内容添加到word中
 Adodc1.Recordset("状态") = "1"
End If
Next i
End If


哪些高手帮我看一下,这个结果会出现重复的记录,错在哪里?

16 个解决方案

#1


本帖最后由 bcrun 于 2012-11-29 15:57:58 编辑
查询时就排除状态 = '1' 的记录。选中的记录写状态后,重新查询。

Adodc1.CommandType = adCmdText
txtsql11 = "select * from " & Trim(Combo11.Text) & "试题 where 题型='" & Trim(Combo1.Text) & "' AND 状态='1'"
Adodc1.RecordSource = txtsql11
Adodc1.Refresh
Adodc1.Recordset.MoveLast
Adodc1.Recordset.MoveFirst '这两句确保得到准确的记录数
Randomize
If Adodc1.Recordset.RecordCount >= Val(Trim(Text9.Text)) Then
For i = 1 To Val(Trim(Text9.Text))  //text9是总共产生多少条不重复的记录数
 n = Int(Rnd() * (Adodc1.Recordset.RecordCount + 1)) 
 For j = 1 To n - 1                   //此循环是为了将指针指向随机产生的第n条记录
 Adodc1.Recordset.MoveNext
 Next j
.Content.InsertAfter (i & "、" & Adodc1.Recordset("题目")) & vbCr //将表中的题目字段内容添加到word中
 Adodc1.Recordset("状态") = "1"
 Adodc1.Recordset.Requery
 Adodc1.Recordset.MoveLast
 Adodc1.Recordset.MoveFirst
Next i
End If



#2


本帖最后由 bcrun 于 2012-11-29 15:58:43 编辑
引用 1 楼 of123 的回复:
查询时就排除状态 = '1' 的记录。选中的记录写状态后,重新查询。

Adodc1.CommandType = adCmdText
txtsql11 = "select * from " & Trim(Combo11.Text) & "试题 where 题型='" & Trim(Combo1.Text) & "' AND 状态='1'"
Adodc1.Re……


非常感谢你的帮助,但我按你这样改,但提示环境变量不可用,指向Adodc1.Recordset.Requery,我在前加了条adodc1.recordset.update,不提示出错,代码如下:但导出的记录还是有重复的。
Dim txtsql11 As String
Adodc1.CommandType = adCmdText
txtsql11 = "select * from " & Trim(Combo11.Text) & "试题 where 题型='" & Trim(Combo1.Text) & "' AND 状态=1"
Adodc1.RecordSource = txtsql11
Adodc1.Refresh
Adodc1.Recordset.MoveLast
Adodc1.Recordset.MoveFirst '这两句确保得到准确的记录数
If Adodc1.Recordset.RecordCount >= Val(Trim(Text9.Text)) Then
For i = 1 To Val(Trim(Text9.Text))  'text9是总共产生多少条不重复的记录数
 Adodc1.Recordset.MoveLast
Adodc1.Recordset.MoveFirst '这两句确保得到准确的记录数
Randomize
 n = Int(Rnd() * (Adodc1.Recordset.RecordCount + 1))
 For j = 1 To n - 1                  '此循环是为了将指针指向随机产生的第n条记录
 Adodc1.Recordset.MoveNext
 Next j
.Content.InsertAfter (i & "、" & Adodc1.Recordset("题目")) & vbCr '将表中的题目字段内容添加到word中
 Adodc1.Recordset("状态") = "1"
 Adodc1.Recordset.Update
 Adodc1.Recordset.Requery
 Adodc1.Recordset.MoveLast
 Adodc1.Recordset.MoveFirst
Next i
End If

#3


其实想要不重复其实很简单,随机函数是有参数的。
比如rnd -1
Randomize password
-1就表示随机函数会记住(继承)上次随机的结果,而且会遵循上一个种子进行随机。
password就是种子,是个长整数。
通常数据库也就几十亿条记录,你一次随机最多生成21亿条,这个数据应该是不会重复的。
当然你可以改变随机种子的大小。最好是让每次随机的种子都不一样。那么才能保证多次随机产生的结果都不一样。
控制一个种子不相同很容易。那么每次随机的结果,才会相互不重复。

#4


我的意思是说,用一个种子,去生成几亿个随机数,是不会重复的。不是说每个随机数都要不同的种子。测试下面的代码。你就明白了。
Private Sub Command1_Click()
Rnd -1
Randomize 3654215
For i = 0 To 5000000
Print 999999 * Rnd
Next
End Sub

#5


你看一下,重新查询后,得到的记录数是否少了 1 条。

你注意一下,你的状态字段是什么类型?我看到你前后是不一样的。查询语句里按照数值型,赋值语句里用的是字符型。

问题可能出在这里。

#6


引用 4 楼 haprince 的回复:
我的意思是说,用一个种子,去生成几亿个随机数,是不会重复的。不是说每个随机数都要不同的种子。测试下面的代码。你就明白了。


Visual Basic code?



1234567

Private Sub Command1_Click() Rnd -1 Randomize 3654215 For i = 0 To 5000000 Print 999999 * Rnd Nex……



谢谢你的回复,我是希望在一个表中满足一定条件的范围内来产生一个随机,然后来根据随机数来确定某一条记录,显示出来,我按你的说法,在randomize后加一个大数,但出来的结果也有重复的,可能是我的范围比较小吧,我是只有15条记录,要随机产生10条不重复的记录

#7


引用 5 楼 of123 的回复:
你看一下,重新查询后,得到的记录数是否少了 1 条。

你注意一下,你的状态字段是什么类型?我看到你前后是不一样的。查询语句里按照数值型,赋值语句里用的是字符型。

问题可能出在这里。


记录没有少,状态字段类型是数值型,查询语句里不能有状态的条件,只为我最初将所有状态都设置为0了的,如果加了状态=1的条件后一条记录都不会满足。所以修改如下,但结果还是有重复的
Dim txtsql11 As String
Adodc1.CommandType = adCmdText
txtsql11 = "select * from " & Trim(Combo11.Text) & "试题 where 题型='" & Trim(Combo1.Text) & "'"
Adodc1.RecordSource = txtsql11
Adodc1.Refresh
'Adodc1.Recordset.MoveLast
'Adodc1.Recordset.MoveFirst '这两句确保得到准确的记录数

If Adodc1.Recordset.RecordCount >= Val(Trim(Text9.Text)) Then
For i = 1 To Val(Trim(Text9.Text))  'text9是总共产生多少条不重复的记录数
 Adodc1.Recordset.MoveLast
Adodc1.Recordset.MoveFirst '这两句确保得到准确的记录数
Randomize 325543
 n = Int(Rnd() * (Adodc1.Recordset.RecordCount + 1))
 For j = 1 To n - 1                  '此循环是为了将指针指向随机产生的第n条记录
 Adodc1.Recordset.MoveNext
 Next j
.Content.InsertAfter (i & "、" & Adodc1.Recordset("题目")) & vbCr '将表中的题目字段内容添加到word中
 Adodc1.Recordset("状态") = 1
 Adodc1.Recordset.Update
 Adodc1.Recordset.Requery
 Adodc1.Recordset.MoveLast
 Adodc1.Recordset.MoveFirst
Next i
End If

#8


你还没有看懂种子的用途,那不是加大数,那是种子。随机函数是有两个参数的,可以选择是什么方式随机。使用-1可以让随机数不出现重复。你从哪里看到加一个大数了。

#9


随机函数的参数,可以保证这次随机的N个结果不重复,但是要保证与数据库内的随机结果不重复,就要用到种子了。
Rnd -1 
Randomize Recordset.RecordCount
mi=100
ma=300
For i = 0 To 50
rs(id)=mi+ Rnd * (ma - mi)
Next
这样用记录总数可以保证每次随机的结果都不重复,又能保证本次所有随机结果跟数据库里的不重复。
同时又指定了一个随机的范围,mi是最小值,ma是最大值。

#10


你没有指定随机函数工作的状态,直接使用就是 任意随机的。产生几个随机数,重复的概率非常大,指定继承方式,结果就不会重复。

#11


引用 9 楼 haprince 的回复:
随机函数的参数,可以保证这次随机的N个结果不重复,但是要保证与数据库内的随机结果不重复,就要用到种子了。
Rnd -1 
Randomize Recordset.RecordCount
mi=100
ma=300
For i = 0 To 50
rs(id)=mi+ Rnd * (ma - mi)
Next
这样用记录总数可以保证每次随机的结果都不重复,又能保证本次所有随机结果跟数……



产生的数是不重复的小数,取整后又会出现重复的,怎么办,谢谢

#12


offset = Int(99 * Rnd) Mod 99

  语法:   Rnd[(number)]   如果 number 的值是 Randomize 生成   小于 0 ,每次都使用 number 作为随机数种子得到的相同结果。   大于 0 ,以上一个随机数为种子产生下一个随机数。   等于 0 ,产生与最近生成的随机数相同的随机数。   省略, 以上一个随机数为种子产生下一个随机数。 

#13


原写法是这样offset = Int((95 + 1) * Rnd)
ch = ((ch + offset) Mod 95)
ch是上一次产生的结果。offset是本次变化的值。

#14


txtsql11 = "select * from " & Trim(Combo11.Text) & "试题 where 题型='" & Trim(Combo1.Text) & "' AND 状态<>'1'"

这样获得未加入的记录。

#15


生成试卷前,可以

Adodc1.RecordSource.ActiveConnection.Execute "Update " & Trim(Combo11.Text) & "试题 Set 状态='0'"

查询中加状态筛选,就是要在查询中去掉已经使用的记录。你每次 Requery 之后,记录数应减少 1。得到的记录集都是未用的记录,因此不重复。

#16


随机数是7位,保证不重复,必须结果×9999999以上,这样的整数才会不重复。

#1


本帖最后由 bcrun 于 2012-11-29 15:57:58 编辑
查询时就排除状态 = '1' 的记录。选中的记录写状态后,重新查询。

Adodc1.CommandType = adCmdText
txtsql11 = "select * from " & Trim(Combo11.Text) & "试题 where 题型='" & Trim(Combo1.Text) & "' AND 状态='1'"
Adodc1.RecordSource = txtsql11
Adodc1.Refresh
Adodc1.Recordset.MoveLast
Adodc1.Recordset.MoveFirst '这两句确保得到准确的记录数
Randomize
If Adodc1.Recordset.RecordCount >= Val(Trim(Text9.Text)) Then
For i = 1 To Val(Trim(Text9.Text))  //text9是总共产生多少条不重复的记录数
 n = Int(Rnd() * (Adodc1.Recordset.RecordCount + 1)) 
 For j = 1 To n - 1                   //此循环是为了将指针指向随机产生的第n条记录
 Adodc1.Recordset.MoveNext
 Next j
.Content.InsertAfter (i & "、" & Adodc1.Recordset("题目")) & vbCr //将表中的题目字段内容添加到word中
 Adodc1.Recordset("状态") = "1"
 Adodc1.Recordset.Requery
 Adodc1.Recordset.MoveLast
 Adodc1.Recordset.MoveFirst
Next i
End If



#2


本帖最后由 bcrun 于 2012-11-29 15:58:43 编辑
引用 1 楼 of123 的回复:
查询时就排除状态 = '1' 的记录。选中的记录写状态后,重新查询。

Adodc1.CommandType = adCmdText
txtsql11 = "select * from " &amp; Trim(Combo11.Text) &amp; "试题 where 题型='" &amp; Trim(Combo1.Text) &amp; "' AND 状态='1'"
Adodc1.Re……


非常感谢你的帮助,但我按你这样改,但提示环境变量不可用,指向Adodc1.Recordset.Requery,我在前加了条adodc1.recordset.update,不提示出错,代码如下:但导出的记录还是有重复的。
Dim txtsql11 As String
Adodc1.CommandType = adCmdText
txtsql11 = "select * from " & Trim(Combo11.Text) & "试题 where 题型='" & Trim(Combo1.Text) & "' AND 状态=1"
Adodc1.RecordSource = txtsql11
Adodc1.Refresh
Adodc1.Recordset.MoveLast
Adodc1.Recordset.MoveFirst '这两句确保得到准确的记录数
If Adodc1.Recordset.RecordCount >= Val(Trim(Text9.Text)) Then
For i = 1 To Val(Trim(Text9.Text))  'text9是总共产生多少条不重复的记录数
 Adodc1.Recordset.MoveLast
Adodc1.Recordset.MoveFirst '这两句确保得到准确的记录数
Randomize
 n = Int(Rnd() * (Adodc1.Recordset.RecordCount + 1))
 For j = 1 To n - 1                  '此循环是为了将指针指向随机产生的第n条记录
 Adodc1.Recordset.MoveNext
 Next j
.Content.InsertAfter (i & "、" & Adodc1.Recordset("题目")) & vbCr '将表中的题目字段内容添加到word中
 Adodc1.Recordset("状态") = "1"
 Adodc1.Recordset.Update
 Adodc1.Recordset.Requery
 Adodc1.Recordset.MoveLast
 Adodc1.Recordset.MoveFirst
Next i
End If

#3


其实想要不重复其实很简单,随机函数是有参数的。
比如rnd -1
Randomize password
-1就表示随机函数会记住(继承)上次随机的结果,而且会遵循上一个种子进行随机。
password就是种子,是个长整数。
通常数据库也就几十亿条记录,你一次随机最多生成21亿条,这个数据应该是不会重复的。
当然你可以改变随机种子的大小。最好是让每次随机的种子都不一样。那么才能保证多次随机产生的结果都不一样。
控制一个种子不相同很容易。那么每次随机的结果,才会相互不重复。

#4


我的意思是说,用一个种子,去生成几亿个随机数,是不会重复的。不是说每个随机数都要不同的种子。测试下面的代码。你就明白了。
Private Sub Command1_Click()
Rnd -1
Randomize 3654215
For i = 0 To 5000000
Print 999999 * Rnd
Next
End Sub

#5


你看一下,重新查询后,得到的记录数是否少了 1 条。

你注意一下,你的状态字段是什么类型?我看到你前后是不一样的。查询语句里按照数值型,赋值语句里用的是字符型。

问题可能出在这里。

#6


引用 4 楼 haprince 的回复:
我的意思是说,用一个种子,去生成几亿个随机数,是不会重复的。不是说每个随机数都要不同的种子。测试下面的代码。你就明白了。


Visual Basic code?



1234567

Private Sub Command1_Click() Rnd -1 Randomize 3654215 For i = 0 To 5000000 Print 999999 * Rnd Nex……



谢谢你的回复,我是希望在一个表中满足一定条件的范围内来产生一个随机,然后来根据随机数来确定某一条记录,显示出来,我按你的说法,在randomize后加一个大数,但出来的结果也有重复的,可能是我的范围比较小吧,我是只有15条记录,要随机产生10条不重复的记录

#7


引用 5 楼 of123 的回复:
你看一下,重新查询后,得到的记录数是否少了 1 条。

你注意一下,你的状态字段是什么类型?我看到你前后是不一样的。查询语句里按照数值型,赋值语句里用的是字符型。

问题可能出在这里。


记录没有少,状态字段类型是数值型,查询语句里不能有状态的条件,只为我最初将所有状态都设置为0了的,如果加了状态=1的条件后一条记录都不会满足。所以修改如下,但结果还是有重复的
Dim txtsql11 As String
Adodc1.CommandType = adCmdText
txtsql11 = "select * from " & Trim(Combo11.Text) & "试题 where 题型='" & Trim(Combo1.Text) & "'"
Adodc1.RecordSource = txtsql11
Adodc1.Refresh
'Adodc1.Recordset.MoveLast
'Adodc1.Recordset.MoveFirst '这两句确保得到准确的记录数

If Adodc1.Recordset.RecordCount >= Val(Trim(Text9.Text)) Then
For i = 1 To Val(Trim(Text9.Text))  'text9是总共产生多少条不重复的记录数
 Adodc1.Recordset.MoveLast
Adodc1.Recordset.MoveFirst '这两句确保得到准确的记录数
Randomize 325543
 n = Int(Rnd() * (Adodc1.Recordset.RecordCount + 1))
 For j = 1 To n - 1                  '此循环是为了将指针指向随机产生的第n条记录
 Adodc1.Recordset.MoveNext
 Next j
.Content.InsertAfter (i & "、" & Adodc1.Recordset("题目")) & vbCr '将表中的题目字段内容添加到word中
 Adodc1.Recordset("状态") = 1
 Adodc1.Recordset.Update
 Adodc1.Recordset.Requery
 Adodc1.Recordset.MoveLast
 Adodc1.Recordset.MoveFirst
Next i
End If

#8


你还没有看懂种子的用途,那不是加大数,那是种子。随机函数是有两个参数的,可以选择是什么方式随机。使用-1可以让随机数不出现重复。你从哪里看到加一个大数了。

#9


随机函数的参数,可以保证这次随机的N个结果不重复,但是要保证与数据库内的随机结果不重复,就要用到种子了。
Rnd -1 
Randomize Recordset.RecordCount
mi=100
ma=300
For i = 0 To 50
rs(id)=mi+ Rnd * (ma - mi)
Next
这样用记录总数可以保证每次随机的结果都不重复,又能保证本次所有随机结果跟数据库里的不重复。
同时又指定了一个随机的范围,mi是最小值,ma是最大值。

#10


你没有指定随机函数工作的状态,直接使用就是 任意随机的。产生几个随机数,重复的概率非常大,指定继承方式,结果就不会重复。

#11


引用 9 楼 haprince 的回复:
随机函数的参数,可以保证这次随机的N个结果不重复,但是要保证与数据库内的随机结果不重复,就要用到种子了。
Rnd -1 
Randomize Recordset.RecordCount
mi=100
ma=300
For i = 0 To 50
rs(id)=mi+ Rnd * (ma - mi)
Next
这样用记录总数可以保证每次随机的结果都不重复,又能保证本次所有随机结果跟数……



产生的数是不重复的小数,取整后又会出现重复的,怎么办,谢谢

#12


offset = Int(99 * Rnd) Mod 99

  语法:   Rnd[(number)]   如果 number 的值是 Randomize 生成   小于 0 ,每次都使用 number 作为随机数种子得到的相同结果。   大于 0 ,以上一个随机数为种子产生下一个随机数。   等于 0 ,产生与最近生成的随机数相同的随机数。   省略, 以上一个随机数为种子产生下一个随机数。 

#13


原写法是这样offset = Int((95 + 1) * Rnd)
ch = ((ch + offset) Mod 95)
ch是上一次产生的结果。offset是本次变化的值。

#14


txtsql11 = "select * from " & Trim(Combo11.Text) & "试题 where 题型='" & Trim(Combo1.Text) & "' AND 状态<>'1'"

这样获得未加入的记录。

#15


生成试卷前,可以

Adodc1.RecordSource.ActiveConnection.Execute "Update " & Trim(Combo11.Text) & "试题 Set 状态='0'"

查询中加状态筛选,就是要在查询中去掉已经使用的记录。你每次 Requery 之后,记录数应减少 1。得到的记录集都是未用的记录,因此不重复。

#16


随机数是7位,保证不重复,必须结果×9999999以上,这样的整数才会不重复。