G
Guest
Hi all,
I've modified the Method 2 solution in the following article. However, the
function is being called more times than their are records in query calling
the function. I inserted a static counter in the function. The function
runs through 32767 iterations before it encounters an Overflow error (we've
exceeded the max size of an integer. I originally thought something was
being called recursively. But that doesn't appear to be the case.
ACC2000: How to Create a "Top N Values Per Group" Query
http://support.microsoft.com/kb/210039/en-us
Here are the SQL and function being called from the query:
SELECT qry_Distribution_By_App_Offset.App_Offset,
qry_Distribution_By_App_Offset.Days_To_Sell,
qry_Distribution_By_App_Offset.[Total Apps],
qry_Distribution_By_App_Offset.[Overall Total Apps],
qry_Distribution_By_App_Offset.[Pct Sold]
FROM qry_Distribution_By_App_Offset
WHERE
qry_Distribution_By_App_Offset.Days_To_Sell<=NthInGroup([qry_Distribution_By_App_Offset].[App_Offset]/5,120)
ORDER BY qry_Distribution_By_App_Offset.App_Offset;
Function NthInGroup(GroupID, N)
' Returns the Nth Item in GroupID for use as a Top N per group
' query criteria.
Dim ItemName, GroupIDName, GDC, SearchTable
Dim SQL As String
Dim rs As New ADODB.Recordset
Dim db As New ADODB.Connection
Dim LastNthInGroup As Integer
Static iCounter As Integer
Static LastGroupId(1 To 9, 1 To 1)
If (LastGroupId(GroupID, 1) <> 0) Then
' Returned saved result if function is called with the
' same GroupID more than once in a row.
NthInGroup = LastGroupId(GroupID, 1)
Else
' Set the SQL statement parameters. These are the only items
' that need to be customized in this function.
' Set to Item field name.
ItemName = "Days_To_Sell"
' Set to Group ID field name.
GroupIDName = "App_Offset"
' GroupID Delimiter Character:
' For Text use "'", Date "#", Numeric "", Text "'"
GDC = ""
' Set to search table.
SearchTable = "qry_Distribution_By_App_Offset"
' Build a Top N SQL statement dynamically given N and
' GroupID as parameters. Note that the sort is by the
' item in descending order, in order to get the Top N
' largest items.
SQL = "Select Top " & N & " [" & ItemName & "] "
SQL = SQL & "From [" & SearchTable & "] "
SQL = SQL & "Where [" & GroupIDName & "]=" & GDC & GroupID * 5 & GDC &
" "
SQL = SQL & "Order By [" & ItemName & "] ASC"
' Open up recordset on Top N SQL statement and read the
' last record to get the smallest item in the Top N.
Set db = CurrentProject.Connection
rs.CursorType = adOpenStatic
rs.LockType = adLockReadOnly
rs.ActiveConnection = db
rs.Open Source:=SQL, Options:=adCmdText
If (rs.BOF And rs.EOF) Then
' No matches found, return a null.
LastNthInGroup = Null
NthInGroup = LastNthInGroup
LastGroupId(GroupID, 1) = LastNthInGroup
Else
' Return the smallest Top N item in the group.
rs.MoveLast
LastNthInGroup = rs(ItemName)
NthInGroup = LastNthInGroup
LastGroupId(GroupID, 1) = LastNthInGroup
End If
End If
Debug.Print iCounter & " - " & GroupID * 5 & " - "; LastNthInGroup
iCounter = iCounter + 1
End Function
I've modified the Method 2 solution in the following article. However, the
function is being called more times than their are records in query calling
the function. I inserted a static counter in the function. The function
runs through 32767 iterations before it encounters an Overflow error (we've
exceeded the max size of an integer. I originally thought something was
being called recursively. But that doesn't appear to be the case.
ACC2000: How to Create a "Top N Values Per Group" Query
http://support.microsoft.com/kb/210039/en-us
Here are the SQL and function being called from the query:
SELECT qry_Distribution_By_App_Offset.App_Offset,
qry_Distribution_By_App_Offset.Days_To_Sell,
qry_Distribution_By_App_Offset.[Total Apps],
qry_Distribution_By_App_Offset.[Overall Total Apps],
qry_Distribution_By_App_Offset.[Pct Sold]
FROM qry_Distribution_By_App_Offset
WHERE
qry_Distribution_By_App_Offset.Days_To_Sell<=NthInGroup([qry_Distribution_By_App_Offset].[App_Offset]/5,120)
ORDER BY qry_Distribution_By_App_Offset.App_Offset;
Function NthInGroup(GroupID, N)
' Returns the Nth Item in GroupID for use as a Top N per group
' query criteria.
Dim ItemName, GroupIDName, GDC, SearchTable
Dim SQL As String
Dim rs As New ADODB.Recordset
Dim db As New ADODB.Connection
Dim LastNthInGroup As Integer
Static iCounter As Integer
Static LastGroupId(1 To 9, 1 To 1)
If (LastGroupId(GroupID, 1) <> 0) Then
' Returned saved result if function is called with the
' same GroupID more than once in a row.
NthInGroup = LastGroupId(GroupID, 1)
Else
' Set the SQL statement parameters. These are the only items
' that need to be customized in this function.
' Set to Item field name.
ItemName = "Days_To_Sell"
' Set to Group ID field name.
GroupIDName = "App_Offset"
' GroupID Delimiter Character:
' For Text use "'", Date "#", Numeric "", Text "'"
GDC = ""
' Set to search table.
SearchTable = "qry_Distribution_By_App_Offset"
' Build a Top N SQL statement dynamically given N and
' GroupID as parameters. Note that the sort is by the
' item in descending order, in order to get the Top N
' largest items.
SQL = "Select Top " & N & " [" & ItemName & "] "
SQL = SQL & "From [" & SearchTable & "] "
SQL = SQL & "Where [" & GroupIDName & "]=" & GDC & GroupID * 5 & GDC &
" "
SQL = SQL & "Order By [" & ItemName & "] ASC"
' Open up recordset on Top N SQL statement and read the
' last record to get the smallest item in the Top N.
Set db = CurrentProject.Connection
rs.CursorType = adOpenStatic
rs.LockType = adLockReadOnly
rs.ActiveConnection = db
rs.Open Source:=SQL, Options:=adCmdText
If (rs.BOF And rs.EOF) Then
' No matches found, return a null.
LastNthInGroup = Null
NthInGroup = LastNthInGroup
LastGroupId(GroupID, 1) = LastNthInGroup
Else
' Return the smallest Top N item in the group.
rs.MoveLast
LastNthInGroup = rs(ItemName)
NthInGroup = LastNthInGroup
LastGroupId(GroupID, 1) = LastNthInGroup
End If
End If
Debug.Print iCounter & " - " & GroupID * 5 & " - "; LastNthInGroup
iCounter = iCounter + 1
End Function