Jürgen Welz
jwelz at hotmail.com
Fri Feb 10 15:28:55 CST 2006
Of course, after I posted, I had to try another method. The query is: SELECT tblEmployee.ContactID, [FirstName] & ' ' & [LastName] AS Expr1 FROM (((tblEmployee INNER JOIN tblEmployeeCourse ON tblEmployee.ContactID = tblEmployeeCourse.EmployeeID) INNER JOIN tblEmployeeCourse AS tblEmployeeCourse_1 ON tblEmployeeCourse.EmployeeID = tblEmployeeCourse_1.EmployeeID) INNER JOIN tblEmployeeCourse AS tblEmployeeCourse_2 ON tblEmployeeCourse.EmployeeID = tblEmployeeCourse_2.EmployeeID) INNER JOIN tblEmployeeCourse AS tblEmployeeCourse_3 ON tblEmployeeCourse.EmployeeID = tblEmployeeCourse_3.EmployeeID WHERE (((tblEmployeeCourse.CourseID)=1) AND ((tblEmployeeCourse_1.CourseID)=2) AND ((tblEmployeeCourse_2.CourseID)=4) AND ((tblEmployeeCourse_3.CourseID)=5)) ORDER BY [FirstName] & ' ' & [LastName]; This is functionally equivalent to creating a query select where CourseID =1, another where CourseID = 2, a third where CouseID = 4 and a 4th where course ID = 5 and then joining them all on the ContactID. A few runs of the time test adding this as a 4th test item result in a time that is 2nd fastest but consistently 70% slower than the fastest method that uses the count. Ciao Jürgen Welz Edmonton, Alberta jwelz at hotmail.com >From: "Jürgen Welz" <jwelz at hotmail.com> > >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 > > >-- >AccessD mailing list >AccessD at databaseadvisors.com >http://databaseadvisors.com/mailman/listinfo/accessd >Website: http://www.databaseadvisors.com