用相关值替换字符串公式的部分

时间:2017-03-17 15:03:07

标签: sql vba access-vba

我有一个表(tbl_Composites),其中包含用于计算性能分数的公式。例如

     KPI       |           FORMULA                | 
--------------------------------------------------
Productivity   |  [ItemsCompleted]/[LoggedInTime] | 
SalesConversion|  [Sales]+[Leads]/[TotalCalls]    | 

还有另一个表格(tbl_BaseData),其中包含一个列,其中包含这些指标以及每个人的相关值

 SCOREDATE | USERID  |    METRIC       | VALUE | 
------------------------------------------------
01/03/2017 | 20511   | ItemsCompleted  |  50   | 
01/03/2017 | 20511   | LoggedInTime    |  320  | 
01/03/2017 | 20630   | Sales           |  8    | 
01/03/2017 | 20630   | Leads           |  3    | 
01/03/2017 | 20630   | TotalCalls      |  25   | 

我正在尝试编写一个VBA函数,该函数将获取Date,UserID和KPI的参数,然后获取该KPI公式的相关度量值并计算结果。

我有一些我设法放在一起的东西,但效率并不高,如果其中一个指标没有记录就行不通(例如有人接听电话但没有销售)。

Function CalulateFormula(strFormula As String, userID As String, scoreDate As Date) As String
Dim Metric As String, valueList As String
Dim i As Integer

For i = 1 To Len(strFormula)
    If Mid(strFormula, i, 1) = "[" Then
        Metric = Mid(strFormula, i + 1, InStr(i + 1, strFormula, "]") - i - 1)
        valueList = valueList & "'" & Metric & "', "
        CalulateFormula = CalulateFormula & Metric
        i = InStr(i + 1, strFormula, "]")
    Else
        CalulateFormula = CalulateFormula & Mid(strFormula, i, 1)
    End If
Next i

valueList = Left(valueList, Len(valueList) - 2)

CalulateFormula = EvaluateSQL(CalulateFormula, valueList, userID, scoreDate)

End Function

这将构建公式字符串并填充它需要查找的指标列表。然后它调用另一个函数,如下所示,它运行一些SQL来获取度量值并评估公式。

Function EvaluateSQL(CalulateFormula As String, valueList As String, userID     As String, scoreDate As Date) As String
Dim strSQL As String
Dim rs As DAO.Recordset

    strSQL = "SELECT Metric, metricValue " & _
         "FROM tbl_BaseData " & _
         "WHERE metric in (" & valueList & ") AND userID = '" & userID & "' AND     scoreDate = #" & Format(scoreDate, "mm/dd/yyyy") & "# "

Set rs = CurrentDb.OpenRecordset(strSQL)

Do Until rs.EOF
    CalulateFormula = Replace(CalulateFormula, rs!Metric, rs!metricValue)
rs.MoveNext
Loop
EvaluateSQL = Eval(CalulateFormula)
End Function

这似乎是一种迂回的做事方式,我想知道我是否需要从一个完全不同的角度来解决问题。任何人都可以告诉我,是否有更简单/更有效的方法,也能够处理空值/缺失值?

1 个答案:

答案 0 :(得分:2)

看起来你过度思考你的字符串生成。 FORMULA的值已包含计算操作/,因此您可以将FORMULA的完整值读作SQL计算。您的FORMULA值中的括号看起来很多,但SQL会将[ItemsCompleted]读作计算的有效字段名称。

比上述更好,你可以完全用SQL代码完成。

您真正需要的是每位用户每天一行。有了它,您可以轻松运行指标;你甚至不需要tbl_Composites表。

所以在这里你是如何做到的:

SELECT
    SCOREDATE
    ,USERID
    ,ItemsCompleted / LoggedInTime as Productivity
    ,Sales + Leads as SalesConversion
    from
    (SELECT distinct 
        base.SCOREDATE, 
        base.USERID, 
        ic.ItemsCompleted,
        lt.LoggedInTime,
        sls.Sales,
        lds.Leads,
        tc.TotalCalls
    from (((((
    tbl_BaseData as base
        left join
            (SELECT SCOREDATE, USERID, VALUE as ItemsCompleted
            from tbl_BaseData
            where METRIC = 'ItemsCompleted') as ic
            on base.USERID = ic.USERID
                and base.SCOREDATE = ic.SCOREDATE)
        left join
            (SELECT SCOREDATE, USERID, VALUE as LoggedInTime
            from tbl_BaseData
            where METRIC = 'LoggedInTime') as lt
            on base.USERID = lt.USERID
                and base.SCOREDATE = lt.SCOREDATE)
        left join
            (SELECT SCOREDATE, USERID, VALUE as Sales
            from tbl_BaseData
            where METRIC = 'Sales') as sls
            on base.USERID = sls.USERID
                and base.SCOREDATE = sls.SCOREDATE)
        left join
            (SELECT SCOREDATE, USERID, VALUE as Leads
            from tbl_BaseData
            where METRIC = 'Leads') as lds
            on base.USERID = lds.USERID
                and base.SCOREDATE = lds.SCOREDATE)
        left join
            (SELECT SCOREDATE, USERID, VALUE as TotalCalls
            from tbl_BaseData
            where METRIC = 'TotalCalls') as tc
            on base.USERID = tc.USERID
                and base.SCOREDATE = tc.SCOREDATE))
        as p

内部查询执行将数据合并到每个用户一行的工作,并记录不存在的记录类型。单独,它返回:

SCOREDATE   USERID  ItemsCompleted   LoggedInTime  Sales  Leads   TotalCalls
01/03/2017  20511   50               320           NULL   NULL    NULL
01/03/2017  20630   NULL             NULL          8      3       25

外部查询然后计算Productivity和SalesConversion。您可以为您需要的任何其他指标添加行。它返回:

SCOREDATE   USERID    Productivity    SalesConversion
01/03/2017  20511     0.156           NULL
01/03/2017  20630     NULL            11