访问2013年的DMedian,未返回任何值

时间:2015-06-09 15:40:38

标签: sql ms-access access-vba

我在MS Access 2013中有以下查询,而不是返回中值。

字段IU始终为NULL(空白)或1.列GM是在-5和5之间格式化0.0000的数字,偶尔会有NULL值。

SELECT IU, DMedian("GM","tblFirst250","IU=1") AS MedianByIU
FROM tblFirst250
WHERE IU = 1
GROUP BY IU;

但是,在尝试调试时,当我使用DAvg而不是DMedian时,我得到一个平均值。

我得到了DMedian(因为我知道Access 2013没有它)来自: https://msdn.microsoft.com/en-us/library/dd789431(v=office.12).aspx

以下是我在名为basDMedian的模块中的代码,作为我数据库的一部分:

Public Function DMedian( _
 ByVal strField As String, ByVal strDomain As String, _
 Optional ByVal strCriteria As String) As Variant

    ' Purpose:
    '     To calculate the median value
    '     for a field in a table or query.
    ' In:
    '     strField: the field.
    '     strDomain: the table or query.
    '     strCriteria: an optional WHERE clause to
    '                  apply to the table or query.
    ' 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 errAppTypeError = 3169

    On Error GoTo HandleErr

    Set db = CurrentDb()

    ' Initialize return value.
    varMedian = Null

    ' Build SQL string for recordset.
    strSQL = "SELECT " & strField & " FROM " & strDomain

    ' Only use a WHERE clause if one is passed in.
    If Len(strCriteria) > 0 Then
        strSQL = strSQL & " WHERE " & strCriteria
    End If

    strSQL = strSQL & " ORDER BY " & strField

    Set rstDomain = db.OpenRecordset(strSQL, dbOpenSnapshot)

    ' Check the data type of the median field.
    intFieldType = rstDomain.Fields(strField).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(strField)
                ' Now move to the next record, the
                ' one right after the middle.
                rstDomain.MoveNext
                ' And average the two values.
                varMedian = _
                  (varMedian + rstDomain.Fields(strField)) / 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 or records.
                ' Move to the middle record and return its value.
                rstDomain.Move ((intRecords \ 2))
                varMedian = rstDomain.Fields(strField)
            End If
        Else
            ' No records; return Null.
            varMedian = Null
        End If
    Case Else
        ' Non-numeric field; so raise an app error.
        Err.Raise errAppTypeError
    End Select

    DMedian = varMedian

ExitHere:
    On Error Resume Next
    rstDomain.Close
    Set rstDomain = Nothing
    Exit Function

HandleErr:
    ' Return an error value.
    DMedian = CVErr(Err.Number)
    Resume ExitHere
End Function

我的目标是获取IU = 1的记录的GM列的中值。我得到的值是NULL /空白。如果有更好的方法,请告诉我。谢谢!

1 个答案:

答案 0 :(得分:2)

要求您的pArray表达式忽略 GM 字段中的任何空值。

DMedian

基本上发生的事情是SELECT IU, DMedian("GM","tblFirst250","IU=1 AND GM Is Not Null") AS MedianByIU FROM tblFirst250 WHERE IU = 1 GROUP BY IU; 打开一个按 GM 排序的记录集,然后(大致)在记录集的一半处移动以获得中值。但如果该行中的值碰巧是空的......

DMedian

... GM -- Null Null <- median 2 告诉你中位数是空的。因此,指示DMedian仅加载DMedian为您提供非空值的中位数的行。