MS Access VBA功能导致查询加载缓慢

问题描述

在使代码更高效时,我需要一些指导。

Public Function fncVAT(ByVal tDate As Variant) As Variant

Dim strTDate As String
Dim strVat As String

tDate = CDate(Nz(tDate,0))

strTDate = "#" & Format(tDate,"mm/dd/yyyy") & "#"
strVat = "SELECT TOP 1 Vat FROM Tax WHERE [EffectiveDate] <= " & strTDate & _
                " ORDER BY [EffectiveDate] DESC;"

    With CurrentDb.OpenRecordset(strVat)
        If Not (.BOF And .EOF) Then
            fncVAT = .Fields(0)
        End If
    End With

End Function

它的作用是根据购买产品的日期应用税表中的当前增值税税率。例如

税表

+----------------+-------+
| Effective Date |  VAT  |
+----------------+-------+
| 9/1/17         | 15%   |
| 2/1/19         | 12.5% |
+----------------+-------+

购买查询

+----------+---------+------+---------+---------------------------------------------------+
| PurDate  | Product | Cost | Vatable |                        Vat                        |
+----------+---------+------+---------+---------------------------------------------------+
| 1/31/18  | Cola    |   70 |       0 | IIf([Vatable]=0,[Cost]*fncVAT([PurDate]),0)=10.50 |
| 12/28/19 | Cola    |   70 |       0 | IIf([Vatable]=0,0)=8.75  |
| 5/3/20   | Flour   |   15 |      -1 | IIf([Vatable]=0,0)=0     |
+----------+---------+------+---------+---------------------------------------------------+

我将其范围缩小到此功能。该查询大约有900条记录,需要一段时间才能加载。有什么建议?预先感谢。

解决方法

最简单的方法可能是修改增值税表,因此它不仅具有每个纳税期的开始日期,还具有结束日期。
当然,当前汇率的EndDate还未知,因此请在此处使用max value

+-----------+------------+-------+
| StartDate |  EndDate   |  VAT  |
+-----------+------------+-------+
| 9/1/17    | 2/1/19     | 15%   |
| 2/1/19    | 12/31/9999 | 12.5% |
+-----------+------------+-------+

然后,您可以在查询中找到匹配的带有JOIN的增值税行,而不再需要该功能:

SELECT p.PurDate,p.Product,p.Cost,p.Vatable,IIf(p.Vatable=0,p.Cost * v.VAT,0) AS Vat
FROM tblProduct p INNER JOIN Vat v 
ON (p.PurDate >= v.StartDate) AND (p.PurDate < v.EndDate)

这应该表现不错。

请注意联接中的> =和 因此,要填充EndDate列,您可以简单地将StartDate块向上复制一行。

,

您为什么需要ORDER BY? ORDER BY通常很慢。我认为您可能想获得最新的税率。因此,ORDER BY在这里,因为您想获得当前适用的税率。我个人会做的是在税收表中创建一个新列,该列告诉我们给定行中的税率是否为当前有效税率。这可以通过将ORDER BY子句分解为一个仅按需运行(根据有效税率的更改)的新查询来完成。每次查询有效税率时都不需要这样做。

查询可能看起来像这样:首先,在Tax表中创建一个新列,称为“ currently_effective”(可以是Number字段),该列指示给定条目中的税率是最新的,即被应用。然后,从VBA脚本执行两个查询。第一个将Tax .. [currently_effective]中的所有值设置为0(假),以便旧值不保存当前有效税率。然后,将Tax。[currently_effective]设置为1(正确),其中该条目具有最新日期。

UPDATE Tax
SET Tax.[currently_effective] = 0

UPDATE Tax
SET Tax.[currently_effective] = 1
WHERE Tax.[EffectiveDate] =
(
SELECT TOP 1 EffectiveDate
FROM Tax
WHERE [EffectiveDate] > @SOME_VALUE
ORDER BY [EffectiveDate] DESC
)

然后您可以在fncVAT中执行SELECT Vat FROM Tax WHERE Tax.[currently_effective] = 1,而且,要获取最新的增值税,我认为您应该在日期中使用“>”,但我不确定您要达到的目标

编辑:

OP,我误会了您的要求。我的解决方案仅适用于新购买的产品。为了将税率应用于现有的购买,我第二次安德烈(Andre)的solution。对我来说,您的功能应该仅不定期地应用于已经存在的购买记录,所以我不明白为什么该功能很慢会导致问题。仅当您定期对新记录使用该功能时,这种速度才会阻碍数据库性能,在这种情况下,我的解决方案仍然适用。