高效随机抽取记录
随机抽取少量记录
如果要从数据表中随机抽取一定数量的记录,例如从员工表随机抽取5个员工,可以参考下面的代码:
Dim
ids As
String
Dim
lst As
new List(of
String)
Dim
cnt As
Integer =
DataTables("员工").DataRows.Count
Do
Dim Id
As Integer
= rand.Next(0,cnt)
id = DataTables("员工").DataRows(id)("_Identify")
If lst.Contains(id)
=False Then
lst.Add(id)
End If
ids =
ids & id
&
","
Loop
While lst.count
< 5
'5是要抽取的行数
Tables("员工").Filter
= "[_Identify] In ("
& ids.Trim(",")
&
")"
上面的代码适合随机抽取少量的记录。
随机抽取大量记录
如果随机抽取的记录较多,可以考虑增加一个逻辑列,假定逻辑列的名称为“选择”,可以参考下面的代码:
Dim
cnt As
Integer = DataTables("订单").DataRows.Count
Dim
nds As
Integer = 100
'要抽取的记录数
Tables("订单").StopRedraw()
DataTables("订单").ReplaceFor("选择",False)
Do
Dim idx
As Integer =
rand.Next(0,cnt)
Dim dr
As DataRow =
DataTables("订单").DataRows(idx)
If dr("选择")
= False Then
dr("选择")
= True
nds =
nds - 1
End
If
Loop
While nds >
0
Tables("订单").Filter
= "[选择] = True"
Tables("订单").ResumeRedraw()
上面的代码从订单表中随机抽取100个订单。
建议逻辑列“选择”采用表达式列,不要给其设置表达式即可,因为:没有设置表达式的表达式列,可以通过代码设置此列的值。
用洗牌法抽取记录
上面的代码在抽取的记录数接近于总的记录数时,性能会下降,虽然可以用逆排除的方法提高性能,但是毕竟要多写一半的代码。
我们可以换个思路,用类似洗牌的方法,将记录顺序打乱后再来抽取,性能会相对比较稳定:
Dim
cnt As
Integer = DataTables("订单").DataRows.Count
Dim
ids1 As
New List(of
Integer)
'用于存储洗牌前的位置
Dim
ids2 As
New List(of
Integer)
'用于存储洗牌后的位置
For
i As
Integer = 0
To cnt -1
'准备初始的牌
ids1.add(i)
Next
For
i As
Integer = 0
To cnt -
1 '开始洗牌
Dim idx
As Integer =
ids1(rand.Next(0,ids1.count))
ids2.Add(idx)
ids1.Remove(idx)
Next
Tables("订单").StopRedraw()
DataTables("订单").ReplaceFor("选择",False)
For
i As
Integer = 0
To 5 -
1 '100为要抽取的行数
DataTables("订单").DataRows(ids2(i))("选择")
= True
Next
Tables("订单").Filter
= "[选择] = True"
Tables("订单").ResumeRedraw()