如何解决创建/运行查询以解决中值功能时遇到问题
这是我第一次尝试对stackoverflow提出问题,因此请原谅提交错误或超出范围
作为VBA的新手程序员,我试图创建并运行查询以执行用户创建的函数,以使用Median()结果创建查询。
我毫不客气地窃了VBA功能的堆栈溢出建议答案。 how to calculate median in Access query using function in VBa 请参阅下面的我的版本。
对该函数的唯一更改是更改了字段名,输入查询名并删除了Optional函数语句,因为它不适用于我的数据集。
查询“ qryMedian”的SQL视图为:
SELECT tblNewOhioAllMedian.AOU2020,tblNewOhioAllMedian.number1,acbdMedian([Number1],"qryMedian") AS MedianResults
FROM tblNewOhioAllMedian
ORDER BY tblNewOhioAllMedian.AOU2020,tblNewOhioAllMedian.number1;
tblNewOhioAllMedian是原始表
AOU2020被定义为双精度数字
Number1是整数
acbdMedian是用户定义的函数
查询和函数均已正确编译,但是查询或函数未正确设置和/或未在两者之间传递结果。
在解决我的问题方面的任何帮助将不胜感激。
函数运行是我对堆栈溢出建议进行了如上所述的修改:
Public Function acbdMedian( _
ByVal Number1 As String,ByVal qryMedian As String) As Variant
' Purpose:
' To calculate the median value
' for a field in a table or query.
' In:
' Number1: The field
' qryMedian: The table or query
' strCriteria: An optional WHERE clause to
' apply to the table or query
' strCriteria value removed as not applicable
' Out:
' Return value: The median,if successful;
' otherwise,an error value
Dim db As DAO.Database
Dim rstDomain As DAO.Recordset
Dim strSQL As String
Dim varMedian As Variant
Dim intFieldType As Integer
Dim intRecords As Integer
Const acbcErrAppTypeError = 3169
On Error GoTo HandleErr
Set db = CurrentDb()
' Initialize the return value.
varMedian = Null
' Build a SQL string for the recordset.
strSQL = "SELECT " & Number1
strSQL = strSQL & " FROM " & qryMedian
' Use a WHERE clause only if one is passed in.
'If Len(strCriteria) > 0 Then
'strSQL = strSQL & " WHERE " & strCriteria
'End If
strSQL = strSQL & " ORDER BY " & Number1
Set rstDomain = db.OpenRecordset(strSQL,dbOpenSnapshot)
' Check the data type of the median field.
intFieldType = rstDomain.Fields(Number1).Type
Select Case intFieldType
Case dbByte,dbInteger,dbLong,dbCurrency,dbSingle,dbDouble,dbDate
' Numeric field.
If Not rstDomain.EOF Then
rstDomain.MoveLast
intRecords = rstDomain.RecordCount
' Start from the first record.
rstDomain.MoveFirst
If (intRecords Mod 2) = 0 Then
' Even number of records. No middle record,so move
' to the record right before the middle.
rstDomain.Move ((intRecords \ 2) - 1)
varMedian = rstDomain.Fields(Number1)
' Now move to the next record,the one right after
' the middle.
rstDomain.MoveNext
' Average the two values.
varMedian = (varMedian + rstDomain.Fields(Number1)) / 2
' Make sure you return a date,even when averaging
' two dates.
If intFieldType = dbDate And Not IsNull(varMedian) Then
varMedian = CDate(varMedian)
End If
Else
' Odd number of records. Move to the middle record
' and return its value.
rstDomain.Move ((intRecords \ 2))
varMedian = rstDomain.Fields(Number1)
End If
Else
' No records; return Null.
varMedian = Null
End If
Case Else
' Nonnumeric field; raise an app error.
Err.Raise acbcErrAppTypeError
End Select
acbdMedian = varMedian
ExitHere:
On Error Resume Next
rstDomain.Close
Set rstDomain = Nothing
Exit Function
HandleErr:
' Return an error value.
acbdMedian = CVErr(Err)
Resume ExitHere
End Function
运行选择查询的结果:
AOU 2020 number1 MedianResults
10 1 #Error
10 1 #Error
10 1 #Error
10 1 #Error
ETC
此查询运行非常缓慢,需要花费几个小时 以该速度完成240,000条记录
我对结果的解释:
每个条目都是一个单独的记录,该函数的结果为#Error
没有计算中位数。
这是最新的测试表:
AOU2020 Number1
1 1
2 1
20 2
10 2
1 2
2 2
20 3
20 3
10 3
10 3
1 3
2 3
10 50
10 50
10 50
10 50
10 50
10 50
10 50
10 50
10 50
10 50
20 60
10 60
20 100
10 100
解决方法
表中有名为Number1的字段吗?字段名称必须在函数参数中的引号内。
无法传递与调用该函数相同的查询名称。
如果您想要每个AOU2020组的中位数,则需要通过过滤条件才能起作用。修改函数声明:
Public Function acbdMedian( _
ByVal Number1 As String,ByVal qryMedian As String,Optional ByVal strCriteria As String) As Variant
通过删除开头的撇号取消注释有关标准的3行:
If Len(strCriteria) > 0 Then
strSQL = strSQL & " WHERE " & strCriteria
End If
要为每个AOU2020返回一条记录,请使用汇总查询。
qryMedian:
SELECT AOU2020,acbdMedian("Number1","tblNewOhioAllMedian","AOU2020=" & [AOU2020]) AS MedianResults
FROM tblNewOhioAllMedian
GROUP BY AOU2020;
具有给定样本数据的结果:
AOU2020 MR
1 2
2 2
10 50
20 3
请注意,由于函数被声明为Variant类型,因此中间值将默认为字符串,并左对齐。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。