Jürgen Welz
jwelz at hotmail.com
Fri Feb 10 14:54:08 CST 2006
Had to try the speed comparisons between the three approaches to querying
"Every Employee who has taken all of the following 4 courses". Tables are
tblEmployee, tblEmployeeCourse (junction table) and tblCourse. There are
1700 employees, about 2000 EmployeeCourse records and 18 course records.
1. Using Count: qryTestCount
SELECT tblEmployeeCourse.EmployeeID, FirstName & ' ' & LastName AS Estimator
FROM tblEmployeeCourse INNER JOIN tblEmployee ON
tblEmployeeCourse.EmployeeID = tblEmployee.ContactID
WHERE (((tblEmployeeCourse.CourseID) In (1,2,4,5)))
GROUP BY tblEmployeeCourse.EmployeeID, FirstName & ' ' & LastName
HAVING (((Count(tblEmployee.ContactID)) = 4))
ORDER BY FirstName & ' ' & LastName;
2. Nested Selects: qryTestNestedIn
SELECT DISTINCT ContactID, FirstName & ' ' & LastName
FROM tblEmployeeEmployeeType RIGHT JOIN tblEmployee ON
tblEmployeeEmployeeType.EmployeeID = tblEmployee.ContactID
WHERE tblEmployee.ContactID > 0 And tblEmployee.Deleted = False And
FirstName > '' And LastName > '' And ContactID In (Select ContactID FROM
tblEmployee INNER JOIN tblEmployeeCourse ON tblEmployee.ContactID =
tblEmployeeCourse.EmployeeID Where ContactID In (Select ContactID FROM
tblEmployee INNER JOIN tblEmployeeCourse ON tblEmployee.ContactID =
tblEmployeeCourse.EmployeeID Where ContactID In (Select ContactID FROM
tblEmployee INNER JOIN tblEmployeeCourse ON tblEmployee.ContactID =
tblEmployeeCourse.EmployeeID Where ContactID In (Select ContactID FROM
tblEmployee INNER JOIN tblEmployeeCourse ON tblEmployee.ContactID =
tblEmployeeCourse.EmployeeID Where CourseID = 1) And CourseID = 2) And
CourseID = 5) And CourseID = 4)
ORDER BY FirstName & ' ' & LastName;
3. Relational Division: qryTestRelationalDiv
SELECT DISTINCT EC1.EmployeeID, [FirstName] & " " & [LastName] AS Expr1
FROM tblEmployeeCourse AS EC1 INNER JOIN tblEmployee ON EC1.EmployeeID =
tblEmployee.ContactID
WHERE (((Exists (SELECT CourseID FROM tblCourse WHERE CourseID In
(1,2,4,5) AND NOT EXISTS ( SELECT * FROM tblEmployeeCourse AS EC2
WHERE EC2.CourseID = tblCourse.CourseID AND EC2.EmployeeID =
EC1.EmployeeID)))=False))
ORDER BY [FirstName] & " " & [LastName];
The following subroutine was used to open each query in sequence and report
to the debug window:
Public Declare Function timeGetTime Lib "Winmm" () As Long
Sub testQuerySpeed()
Dim r As DAO.Recordset
Dim db As DAO.Database
Dim lngi As Long
Dim t As Long
Set db = CurrentDb
t = timeGetTime
For lngi = 0 To 50
Set r = db.OpenRecordset("qryTestCount")
Next
Debug.Print "Using Count " & timeGetTime - t
t = timeGetTime
For lngi = 0 To 50
Set r = db.OpenRecordset("qryTestNestedIn")
Next
Debug.Print "Using Nested Join " & timeGetTime - t
t = timeGetTime
For lngi = 0 To 50
Set r = db.OpenRecordset("qryTestRelationalDiv")
Next
Debug.Print "Using RelationalDivision " & timeGetTime - t
r.Close
Set r = Nothing
End Sub
The results in the immediate window (in milliseconds), run 5 minutes apart
speak for themselves:
Using Count 5219
Using Nested Join 34796
Using RelationalDivision 13563
Using Count 7750
Using Nested Join 53625
Using RelationalDivision 17000
Ciao
Jürgen Welz
Edmonton, Alberta
jwelz at hotmail.com