在查询中使用group by
等功能时,我遇到了使用聚合函数的麻烦。它不是应用于整个查询记录集的聚合函数,而是仅应用于由查询性质确定的选择组。例如:
Person Date Able
-----------------------------
A 21/05/13 0
B 21/05/13 -1
C 21/05/13 -1
D 21/05/13 0
(grouped by Person, Date, Able)
应用聚合函数时:
Person Date Able Max(Able) Min(Date)
----------------------------------------------------
A 21/05/13 0 0 21/05/13
B 22/05/13 -1 -1 22/05/13
C 23/05/13 -1 -1 23/05/13
D 24/05/13 0 0 24/05/13
除非数据完全取消分组,否则聚合函数完全是冗余的。到目前为止,我一直在使用它来解决它:
1)使用另一个查询来引用初始查询并确定真正的聚合值。
2)让表单使用d
函数(dlookup
,dcount
等来调用第二个查询。)
在我的特定场景中,我有一个列表(非常类似于上面)需要以特定顺序呈现(根据ID排名)。但是,我在查询中使用表达式来定义不同类型的排名。这个想法是显示(使用条件格式)这个新排名中的第一个记录。如下图所示
Person Date ID CalculatedRank
--------------------------------------------
A 21/05/13 1 4
B 21/05/13 2 2
C 21/05/13 3 3
D 21/05/13 4 1
理想情况下,我希望有另一个专栏确定哪一个是第一个可以轻松实现的专栏:
first: [CalculatedRank] = Min( [CalculatedRank] )
但如上所述,Min()不给我1,它是按行给出的(最小值不总是1,所以我不能任意设置)。
现在我正在使用单独的查询来引用此第一个查询,并根据计算出的排名对其进行排序。然后,条件格式化可以使用dlookup来确定它是否是第一个查询的第一个。但是,每次表单刷新或调用requery时,每一行的条件格式都会触发另一个dlookup,然后引用每行重新计算新排名的第一个查询!
可以想象,延迟是明显的,导致光标空闲> 5秒。我不太确定访问的内部机制,但是使用内置调试器,对4行记录集的重新查询导致我的CalculateRank()
函数被调用12次,纯粹是通过调用第二个查询的条件格式。
总之,我已经将其缩小到要求单独的查询(因此dlookup)以正确使用聚合函数。如果我能够将所有内容保存在一个查询中,则条件格式化不需要在另一个查询上使用dlookup来确定其状态。
我确信我不是唯一一个遇到此问题的人,并且想知道是否存在任何可以避免所有堆叠查询的解决方案。
一如既往,非常感谢任何帮助!
答案 0 :(得分:1)
Person Date ID
------ ---------- --
A 2013-05-21 1
B 2013-05-21 2
C 2013-05-21 3
D 2013-05-21 4
和我的查询[qryTable1Ranked]
SELECT Table1.*, CalculateRank([ID]) AS CalculatedRank
FROM Table1;
在标准VBA模块中使用以下功能
Public Function CalculateRank(ID As Long) As Long
Dim r As Long
Select Case ID
Case 1
r = 4
Case 4
r = 1
Case Else
r = ID
End Select
CalculateRank = r
Debug.Print "x"
End Function
并返回
Person Date ID CalculatedRank
------ ---------- -- --------------
A 2013-05-21 1 4
B 2013-05-21 2 2
C 2013-05-21 3 3
D 2013-05-21 4 1
当我只是双击查询以在数据表视图中打开它时,我的排名函数被调用4次,每行一次。
如果我根据该查询创建一个连续的表单并打开表单,我的函数会被调用4次。然后,如果我使用Value = DMin("CalculatedRank", "qryTable1Ranked")
在[CalculatedRank]文本框中添加条件格式,那么我的函数将被调用32次!
如果我添加一个名为[txtMinCalculatedRank]的不可见未绑定文本框,我发现可以将其减少一半(至16次),使用表单后面的以下代码...
Option Compare Database
Option Explicit
Private Sub Form_Load()
UpdateMinCalculatedRank
End Sub
Private Sub UpdateMinCalculatedRank()
Me.txtMinCalculatedRank.Value = DMin("CalculatedRank", "qryTable1Ranked")
End Sub
...并将条件格式规则更改为Value = [txtMinCalculatedRank]
。
如果我将表单的Record Source
从qryTable1Ranked
更改为Table1
(基表),我发现我可以将其减半(至8次)并更改[CalculatedRank]文本框Control Source
=CalculateRank([ID])
(仍然使用上一次调整中的技巧)。
我认为可能就像创建临时表一样好,或者在基表中持久存在CalculatedRank(可能还有一个“IsMin”标志)。