Visual Studio中VB.NET统计Access库符合条件记录数
需求可行性判定
按月度维度筛选指定取值的日志记录做统计是Access数据库的常规聚合能力,完全可以实现。
原代码的核心问题
- 参数绑定逻辑错误:对同一个
@MY_OF_LOG参数名连续重复赋值12次,后赋的值会完全覆盖之前的内容,最终整个SQL只会拿12月的日期做一次查询,根本不会逐个统计12个月份的数值 - 日期匹配逻辑错误:原SQL采用
[M/Y OF LOG] = 固定月初日期的匹配规则,但日志存储的是具体到日的实际运行时间,绝大多数日志不会刚好落在每月1号,这种写法会漏掉99%的非1号记录 - 变量赋值逻辑错乱:代码把
OleDbParameterCollection.Add方法的返回值直接赋值给各个月份的计数变量,根本没有接收数据库返回的统计结果,最终绑定到图表的Y轴数值全是参数对象的引用值,不是真实的记录数 - 缺少重复加载规避逻辑:窗体加载时如果触发多次
Load事件,图表会无限制叠加新的数据点
修正后的实现方案
采用单条聚合SQL完成全年所有月份的统计,不需要循环12次查询数据库,执行效率更高,逻辑更稳定。
修正后的完整VB.NET代码
Private Sub CountMissedParts() Handles MyBase.Load ' 初始化月份计数数组,索引0对应X轴基准点,1-12对应1-12月 Dim monthMissedCount(12) As Integer ' 指定统计的年份范围,可根据实际业务调整起止时间 Dim queryStartDate As New Date(2021, 1, 1) Dim queryEndDate As New Date(2021, 12, 31) ' 聚合SQL:按月份分组,一次查询拿到所有满足条件的月度记录数 Dim sqlText As String = " SELECT Month([M/Y OF LOG]) AS LogMonth, COUNT(*) AS MissedTotal FROM DataCollection WHERE [MISSED PART] = 'Missed Part' AND [M/Y OF LOG] BETWEEN @StartDate AND @EndDate GROUP BY Month([M/Y OF LOG]) " ' 复用配置的连接字符串执行查询 Using conn As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Database1.accdb") Using cmd As New OleDb.OleDbCommand(sqlText, conn) ' OLEDB驱动按参数顺序匹配,需和SQL中的参数顺序保持一致 cmd.Parameters.Add("@StartDate", OleDb.OleDbType.Date).Value = queryStartDate cmd.Parameters.Add("@EndDate", OleDb.OleDbType.Date).Value = queryEndDate conn.Open() ' 读取查询结果填充计数数组 Using reader As OleDb.OleDbDataReader = cmd.ExecuteReader() While reader.Read() Dim targetMonth As Integer = reader.GetInt32(0) Dim targetCount As Integer = reader.GetInt32(1) monthMissedCount(targetMonth) = targetCount End While End Using End Using End Using ' 清空图表原有数据点,避免重复加载导致的数值叠加 NotInEpicorCHRT.Series("Missed Part").Points.Clear() ' 绑定基准点和12个月份的统计值 NotInEpicorCHRT.Series("Missed Part").Points.AddXY(0, 0) For monthIndex As Integer = 1 To 12 NotInEpicorCHRT.Series("Missed Part").Points.AddXY(monthIndex, monthMissedCount(monthIndex)) Next ' 配置坐标轴参数 NotInEpicorCHRT.ChartAreas(0).AxisX.Minimum = 0.0 NotInEpicorCHRT.ChartAreas(0).AxisX.Maximum = 12 NotInEpicorCHRT.ChartAreas(0).AxisX.Interval = 1 NotInEpicorCHRT.ChartAreas(0).AxisY.Minimum = 0.0 NotInEpicorCHRT.ChartAreas(0).AxisY.Maximum = 45 NotInEpicorCHRT.ChartAreas(0).AxisY.Interval = 5 End Sub
关键逻辑说明
- 统计规则完全匹配业务要求:只要日志的
MISSED PART值为Missed Part,且日期在查询时间范围内,就会按照日志实际记录的月份归入对应统计组,不会出现日期漏匹配的问题 - 执行效率优化:原本需要12次数据库交互完成的统计,现在单次查询即可完成,大幅降低数据库访问开销
- 空值自动兼容:没有任何满足条件记录的月份,数组会默认保留0值,不需要额外写分支判断补全空月份的统计值
- 适配OLEDB驱动特性:明确按照参数顺序传值,避免Access OLEDB驱动的参数名匹配失效问题
内容的提问来源于stack exchange,提问作者user14823575
相关产品推荐
相关产品推荐

