请高手来帮看看这段代码如何提高效率

slowgrace 2009-04-16 05:14:33
我是在ACCESS的VBA里编程。数据库就用的ACCESS 2003,VBA的代码也是直接就写在同一MDB里。用的是DAO.

下面的代码是用来一次性计算层次百分比。关于层次百分比的概念我解释在这个帖子里:http://blog.csdn.net/slowgrace/archive/2009/04/16/4084636.aspx。下面这段代码对一个有两万多条记录的节点表进行计算时需时20分钟,如果用注释掉那个则需时16分钟。注释掉的部分和没注释掉的部分的区别在,注释掉的用的是DAO的edit和update方法,没注释掉的用的是update语句。我真没想到直接用update语句还慢。但不管是哪种都太慢了,是吧?请各位前辈高人指点:

'算从lngrootid这个根节点开始的所有子节点(含根节点)的金额和百分比
'并把计算结果放在节点表的相应字段里
'返回根节点的值
Public Function CalValuePercent(strNodeTable As String, lngRootId As Long) As Single
On Error GoTo Err_CalValuePercent

Dim rstNode As DAO.Recordset, rstDetail As DAO.Recordset
Dim strSql As String
Dim sngValue As Single
Dim blnNoChild As Boolean

sngValue = 0

'得到每个孩子的值(递归)并累积自己的值(等于所有孩子的值的总和)
strSql = "SELECT lngNodeId FROM " & strNodeTable & " WHERE lngFatherId = " & lngRootId
Set rstNode = CurrentDb.OpenRecordset(strSql)
If rstNode.EOF Then
blnNoChild = True
Else
blnNoChild = False
While Not rstNode.EOF
sngValue = sngValue + CalValuePercent(strNodeTable, rstNode.Fields("lngNodeId")) '递归调用
rstNode.MoveNext
Wend
End If
rstNode.Close
Set rstNode = Nothing

'将自己的值记录到数据库里
If blnNoChild Then
strSql = "SELECT strDetailTable, lngDetailId FROM " & strNodeTable & " WHERE lngNodeId = " & lngRootId
Set rstNode = CurrentDb.OpenRecordset(strSql)
If IsBasicTable3Db(Nz(rstNode.Fields("strDetailTable"))) Then '如果是基础节点,则从基础表抄value过来
strSql = "SELECT sngValue FROM " & rstNode.Fields("strDetailTable") & " WHERE lngId = " & rstNode.Fields("lngDetailId")
Set rstDetail = CurrentDb.OpenRecordset(strSql)
sngValue = Nz(rstDetail.Fields("sngValue"))
rstDetail.Close
Set rstDetail = Nothing
End If
rstNode.Close
Set rstNode = Nothing
End If
strSql = "UPDATE [" & strNodeTable & "] SET [sngValue] = " & sngValue & " WHERE lngNodeId = " & lngRootId
CurrentDb.Execute strSql
' strSql = "SELECT lngNodeId, strDetailTable, lngDetailId, sngValue FROM " & strNodeTable & " WHERE lngNodeId = " & lngRootId
' Set rstNode = CurrentDb.OpenRecordset(strSql)
' If blnNoChild And IsBasicTable3Db(Nz(rstNode.Fields("strDetailTable"))) Then '如果是基础节点,则从基础表抄value过来
' strSql = "SELECT sngValue FROM " & rstNode.Fields("strDetailTable") & " WHERE lngId = " & rstNode.Fields("lngDetailId")
' Set rstDetail = CurrentDb.OpenRecordset(strSql)
' sngValue = Nz(rstDetail.Fields("sngValue"))
' rstDetail.Close
' Set rstDetail = Nothing
' End If
' rstNode.Edit
' rstNode.Fields("sngValue") = sngValue
' rstNode.Update
' rstNode.Close
' Set rstNode = Nothing


'计算每个孩子的百分比
If Not blnNoChild Then
strSql = "UPDATE [" & strNodeTable & "] SET [sngPercent] = " & _
"IIF(" & sngValue & "=0, 0, [sngValue]/" & sngValue & ") " & _
"WHERE [lngFatherId]=" & lngRootId
CurrentDb.Execute strSql

' strSql = "SELECT lngNodeId, sngValue, sngPercent FROM " & strNodeTable & " WHERE lngFatherId = " & lngRootId
' Set rstNode = CurrentDb.OpenRecordset(strSql)
' While Not rstNode.EOF
' rstNode.Edit
' If sngValue = 0 Then
' rstNode.Fields("sngPercent") = 0
' Else
' rstNode.Fields("sngPercent") = rstNode.Fields("sngValue") / sngValue
' End If
' rstNode.Update
' rstNode.MoveNext
' Wend
' rstNode.Close
' Set rstNode = Nothing
End If

CalValuePercent = sngValue
Exit Function

Err_CalValuePercent:
Stop
Debug.Print ERR.Description
Resume
End Function



...全文
124 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
slowgrace 2009-04-21
  • 打赏
  • 举报
回复
问题解决了一部分

没有可用分了

就此结帖

感谢wwwww
wwwwb 2009-04-17
  • 打赏
  • 举报
回复
呵呵,是这样
slowgrace 2009-04-17
  • 打赏
  • 举报
回复
另外 wwwwa是不是你的马甲啊?

你们俩的名字好有意思啊
wwwwb 2009-04-17
  • 打赏
  • 举报
回复
呵呵,我也不知道,从来没有 用过,呵呵
slowgrace 2009-04-17
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 wwwwb 的回复:]
你的博客不错,学习

我是不是有可能把这整个函数写成1个查询啊?如果能,是不是能快不少?
递归查询是不行的

个人观点,参数查询还不如直接用字符串累加得到SQL语句,再执行
[/Quote]

呵呵,被你这么一夸,立马跑到博客去自我欣赏一番。谢谢哈。另外,我怎么加不上你好友啊。发了好几次消息,好像都死机了似的?
wwwwb 2009-04-17
  • 打赏
  • 举报
回复
你的博客不错,学习

我是不是有可能把这整个函数写成1个查询啊?如果能,是不是能快不少?
递归查询是不行的

个人观点,参数查询还不如直接用字符串累加得到SQL语句,再执行
slowgrace 2009-04-17
  • 打赏
  • 举报
回复
另外,to aaaa,我把搜集的access存储过程的信息整理在这个文章里:http://blog.csdn.net/slowgrace/archive/2009/04/16/4085118.aspx

貌似就是参数查询。不知对性能能有多大帮助?你的感觉如何呢?
slowgrace 2009-04-16
  • 打赏
  • 举报
回复
建了索引还真管用。我在两个字段上加了索引:lngNodeId, lngFatherId。速度提升不少。

用执行update查询的方法共需4分钟;用DAO的方法共需6分钟。

看来用查询比直接执行DAO的方法要快。我是不是有可能把这整个函数写成1个查询啊?如果能,是不是能快不少?
WWWWA 2009-04-16
  • 打赏
  • 举报
回复
下班了,明天再看看
slowgrace 2009-04-16
  • 打赏
  • 举报
回复
哦 谢谢 试试先

另外,今天早上找到一篇文章,还没来及细看,关于ACCESS SP的:http://access911.net/fixhtm/79FAB21E12DC.htm?tt=
WWWWA 2009-04-16
  • 打赏
  • 举报
回复
就是在查询字段上,你的是lngFatherId上建立索引试试,
进入ACCESS,控制面板->表->设计->点lngFatherId字段,下面属性
中有索引,设置有(无重复)

另外,用存储过程不知道能否快一些?:
如果你用ACCESS的话,ACCESS没有SP
slowgrace 2009-04-16
  • 打赏
  • 举报
回复
谢谢aaaa

我很菜,没用过索引。能否稍微详细一些?

另外,用存储过程不知道能否快一些?
WWWWA 2009-04-16
  • 打赏
  • 举报
回复
VBA应该比ADO快一些,建立索引试试吧,这种递归查询速度快不了,
因为有循环

7,714

社区成员

发帖
与我相关
我的任务
社区描述
Microsoft Office Access是由微软发布的关系数据库管理系统。它结合了 MicrosoftJet Database Engine 和 图形用户界面两项特点。
社区管理员
  • Access
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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