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