3 4
Now that you've had a chance to work with some queries, you're ready to advance to the next level. But first you need to understand how relationships affect a query. You've already learned that you can base a query on more than one data source and that a data source can be a table or a query. When you add more than one data source to the Design view, the query inherits any relationships created via the Relationships window. Access represents those relationships by displaying a join line between the related fields, as shown in Figure 9-38.
Figure 9-38. Join lines indicating relationships between tables in query Design view.
InsideOut
Access won't update existing queries to reflect changes made to relationships in the query Design view. You'll have to open any existing queries that might be affected by your changes and create the relationship (or relationships) yourself.
The join line tells a lot about the existing relationship. In Figure 9-38, the join line includes a 1 near the CustomerID field of the Customers table and an infinity symbol (8) near the CustomerID field of the Orders table. The 1 and the infinity symbol indi
cate a one-to-many relationship, which means that there can be many orders for any one customer, but only one customer per order. There's also a one-to-many relationship between the Orders table and the Order Details table based on the OrderID field. This relationship indicates that each order in the Orders table will have one or more detail records in the Order Details table. The presence of the 1 and the infinity symbol is a visual clue that the relationship enforces referential integrity -rules that restrict when you can add and delete records. When a relationship is indeterminate, Access displays the join line, but no symbols. You can temporarily sever a relationship (for the current query only) by clicking the join line and pressing Delete.
For more information about types of relationships and referential integrity, see Chapter 4, "Creating a Database."
Access can still define a relationship between two tables even if you haven't created a relationship yourself. By default, Access creates a relationship between two tables in a query if both of the following conditions are true:
Both tables contain a common field of the same name and data type. There is one exception to this rule: You can relate an AutoNumber field to a Long Integer (if the Field Size property in both is set to Replication ID). You can manually create a relationship between fields of the same data type-even if their names don't match-by dragging a primary key field from one field list to the related field (foreign key field) in another list. All Access really requires in this case is that the fields be of the same data type. If you want Access to create the relationship automatically, the field names must match.
At least one of the fields is a primary key field. This means that every record in the table has a unique value in this field.
You won't always want Access to automatically create a relationship between tables. To turn off this AutoJoin feature, choose Tools, Options, and then click the Tables/Queries tab and clear the Enable AutoJoin check box. Disabling this feature works only with unrelated tables. Permanent relationships established via the Relationships window will still take precedence in a query.
note
A Cartesian Product
Most multiple-table queries are based on related tables. If tables in a query aren't joined, Access won't know how to associate records. In this case, Access will create a cross (Cartesian) product. That means that Access will join every record in every table. A query based on two unrelated tables-for example, a table with 10 records and another with 20 records-will return 200 records. As a rule, you won't run into this type of query very often.
A self-join combines records from the same table. In other words, you're relating a table to itself. Although not commonly used, a self-join helps you find records that have common values with other records in the same table.
The Northwind Employees table assigns a unique value to each employee by using an AutoNumber field. In addition, the ReportsTo field stores the corresponding manager's AutoNumber value. As a result of this efficient arrangement, you won't need a second table to identify managers. The ReportsTo field displays names, but they're the result of a lookup field, which you need to delete. (You're deleting this feature so you can review a self-join, not because there's anything wrong with the lookup field method of displaying each manager's name.)
tip
To delete the lookup field, follow these steps:
Figure 9-39. The Employees table in Design view.
Take a look at the modified Employees table, shown in Figure 9-40. (Several of the fields that you don't need are hidden.) The ReportsTo field now displays each manager's EmployeeID value.
Figure 9-40. After you delete the lookup field, the ReportsTo field identifies the employee's manager by EmployeeID instead of by name.
To create a self-join query that identifies the manager by name instead of by the EmployeeID value, follow these steps:
Access adds a second instance of the table and assigns the default name Employees_1, as shown in Figure 9-41.
Figure 9-41. Two Employees tables shown in query Design view. Access gives the second instance of the Employees table the name Employees_1.
Figure 9-42. Change the Alias property for the Employees_1 table.
note
Manager: [Managers].[FirstName] & " " & [Managers].[LastName]
This expression concatenates the contents of the FirstName and LastName fields with a space in between. When finished, the query Design view should look like Figure 9-43.
Figure 9-43. Add a calculated field to the self-join query.
Figure 9-44. The calculated Manager field contains the name of each employee's manager.
There's one problem with the results of this self-join query: Andrew Fuller is not listed in the FirstName and LastName fields. That's because his ReportsTo field is blank, and the default join is an INNER JOIN (the default relationship), which returns only those records in which the values are the same in the related field. You can see this by viewing the query's Jet SQL statement:
SELECT Employees.LastName, Employees.FirstName, Employees.Title, [Managers].[FirstName] & " " & [Managers].[LastName] AS Manager FROM Employees INNER JOIN Employees AS Managers ON Employees.ReportsTo = Managers.EmployeeID;
Access defaults to an INNER JOIN. This query displays those records in which the ReportsTo entry matches an EmployeeID entry. Since Andrew Fuller has no ReportsTo entry, the INNER JOIN omits this record from the results.
This query will include Andrew Fuller if you change the join type to a LEFT JOIN. A LEFT JOIN returns all the records in the left table (Employees) of the join operation, but in the right table (Managers), it returns only the records that match the related field.
To change the join type, follow these steps:
Figure 9-45. Make the join a LEFT JOIN.
Figure 9-46. This time the query includes Andrew Fuller.
The modified Jet SQL statement is shown here:
SELECT Employees.LastName, Employees.FirstName, Employeees.Title, [Managers].[FirstName] & " " & [Managers].[LastName] AS Manager FROM Employees LEFT JOIN Employees AS Managers ON Employees.ReportsTo = Managers.EmployeeID;
The statement is the same as the previous statement, except the type of join is now a LEFT JOIN. The results confirm this, as they display all the records in the Employees table, including the record for Andrew Fuller.
tip - Change a field's name in a query