chapter06 oracle

40
Chapter 6 CHAPTER 6 ----------------------------------------------------------------- ---------------------------------------------------- JOINS This chapter focuses on JOIN operations. Thus far, your study of the SQL has focused on writing queries that retrieve data stored in a single table. However, large databases have many related tables. Often, managers need information that requires the retrieval of data from related rows that are stored in more than one table. These queries are termed JOIN operations, and may include data rows from two, three, or even more related tables. OBJECTIVES OBJECTIVES The related tables of a large database are linked through the use of foreign and primary keys or what are often referred to as common columns. In this chapter, you will learn to join tables together based on foreign and primary keys. The ability to join tables will enable you to add more meaning to the result table that is produced. Writing table joins is a task SQL programmers accomplish routinely. Your learning objectives for this chapter include: Write an equijoin query and inequality join by using the WHERE clause. Learn the basic JOIN operation rules. Write complex JOIN queries with more than two tables, and more than two columns. Write OUTER JOIN queries. Write SELF-JOIN queries. Use the NATURAL keyword to specify an equijoin query. A TYPICAL JOIN OPERATION A TYPICAL JOIN OPERATION Figure 6.1 displays the employee and department tables. The figure illustrates the concept of a JOIN operation by connecting columns Revised September 22, 2007 6 - 1

Upload: kamalprabha

Post on 21-Apr-2015

67 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Chapter06 Oracle

Chapter 6

CHAPTER 6---------------------------------------------------------------------------------------------------------------------

JOINS

This chapter focuses on JOIN operations. Thus far, your study of the SQL has focused on writing queries that retrieve data stored in a single table. However, large databases have many related tables. Often, managers need information that requires the retrieval of data from related rows that are stored in more than one table. These queries are termed JOIN operations, and may include data rows from two, three, or even more related tables.

OBJECTIVESOBJECTIVES

The related tables of a large database are linked through the use of foreign and primary keys or what are often referred to as common columns. In this chapter, you will learn to join tables together based on foreign and primary keys. The ability to join tables will enable you to add more meaning to the result table that is produced. Writing table joins is a task SQL programmers accomplish routinely. Your learning objectives for this chapter include:

Write an equijoin query and inequality join by using the WHERE clause. Learn the basic JOIN operation rules. Write complex JOIN queries with more than two tables, and more than two columns. Write OUTER JOIN queries. Write SELF-JOIN queries. Use the NATURAL keyword to specify an equijoin query.

A TYPICAL JOIN OPERATIONA TYPICAL JOIN OPERATION

Figure 6.1 displays the employee and department tables. The figure illustrates the concept of a JOIN operation by connecting columns within each table with a line. One line connects the employee table's DepartmentNumber column with the department table's DepartmentNumber column. The fact that each column has the same name is not relevant. The important fact is that the two columns store data values that share a common domain of values. The two columns could have different names; however, as long as they share a common domain of values the two tables can be joined based on these columns. Columns like this often have the same name because it is convenient and easier to identify columns with common domains in this fashion.

The domain of values for the DepartmentNumber column in the employee table is all valid department numbers. This means that, because of the referential integrity clauses enforced when the tables were created, the values stored in the DepartmentNumber column of employee must also appear in the DepartmentNumber column for one of the rows in the department table.

A second line connects the employee table's EmployeeID column to the department table's ManagerID column. While the column names are different, these two columns share a common domain of values. This line represents a second, different JOIN operation. This second JOIN operation enables the display of detailed information about a department manager since the only information stored in the department table about each department's manager is the manager's identifying number (ManagerID).

Revised September 22, 2007 6 - 1

Page 2: Chapter06 Oracle

Chapter 6

Figure 6.1

If you review the SQL script used to create the employee and department tables, you will discover that it is possible for an employee to NOT be assigned to a specific department. However, this situation would only arise if a department is eliminated (deleted) from the database. In this case, the DepartmentNumber column value for employees assigned to the deleted department is set to NULL pending the reassignment of each employee to a new department.

We will begin our study of JOIN operations by focusing on the relationship between the employee and department tables represented by the common department number values. The first query in SQL Example 6.1 lists employee names and department numbers. This query only retrieves data from the single employee table.

/* SQL Example 6.1 */COLUMN "Last Name" FORMAT A15;COLUMN "First Name" FORMAT A15;COLUMN "Dept" FORMAT 9999;SELECT LastName "Last Name", FirstName "First Name", DepartmentNumber "Dept"FROM EmployeeORDER BY LastName, FirstName;

Last Name First Name Dept--------------- --------------- -----Adams Adam 8Barlow William 3Becker Robert 3more rows will be displayed . . .

A large organization can have dozens or even hundreds of departments. Thus, the numbers displayed in the department column shown above may not be very meaningful. In this situation, a manager may want the result table to display the department name instead of the department number. This requires you to retrieve information from two tables since department names are not stored in the employee table; rather, they are stored in the department table.

Revised September 22, 2007 6 - 2

Page 3: Chapter06 Oracle

Chapter 6

Hence, your query needs to join the employee and the department tables in order to produce the desired result table.

Joins can be specified in either the FROM or WHERE clauses. The join conditions combine with the WHERE and HAVING search conditions to control the rows that are selected from the tables referenced in the FROM clause. Originally Oracle SQL used the WHERE clause to join tables. Use of the WHERE clause to join tables was one of the early standards for SQL. The newer American National Standards Institute (ANSI) and International Standards Organization (ISO) ANSI/ISO SQL-92 standard uses the FROM clause to carry out a JOIN operation. The older syntax is, however, still valid, and is expected to remain valid in the future (except for OUTER JOIN operations discussed later in this chapter). We first examine a JOIN operation using the WHERE clause because you are already familiar with WHERE clauses.

Study the query in SQL Example 6.2. In this query, the WHERE clause links the employee table's DepartmentNumber column to the department table's DepartmentNumber column. Since the query retrieves row data from two tables, each table is listed in the FROM clause. The query is also shown with the use of alias names in SQL Example 6.3. While the use of an alias name is optional, you will find this approach is common because it reduces the amount of typing required and shortens the JOIN portion of the SQL SELECT statement. The employee table's alias name is simply the letter "e" while the department table's alias is the letter "d." Table alias names are used to enable an abbreviated method for referencing a table name within the query.

/* SQL Example 6.2 Query using full table names */COLUMN "Department Name" FORMAT A30;SELECT LastName "Last Name", FirstName "First Name", DepartmentName "Department Name"FROM Employee, DepartmentWHERE Employee.DepartmentNumber = Department.DepartmentNumberORDER BY LastName, FirstName;

/* SQL Example 6.3 Same query with alias names */SELECT LastName "Last Name", FirstName "First Name", DepartmentName "Department Name"FROM Employee e, Department dWHERE e.DepartmentNumber = d.DepartmentNumberORDER BY LastName, FirstName;

Last Name First Name Department Name--------------- --------------- ------------------------------Adams Adam Admin/LabsBarlow William Emergency-SurgicalBecker Robert Emergency-Surgicalmore rows will be displayed . . .

The newer syntax based on the ANSI/ISO SQL-92 standard writes the join condition explicitly by using a combination of JOIN and ON keywords within the FROM clause. This allows the WHERE clause to be focused on specifying the criteria for selecting the data rows to be included in the result table. This syntax is shown in SQL Example 6.4. Note that the WHERE clause does not handle the join condition. The FROM clause explicitly specifies the JOIN in addition to listing the tables and assigning the aliases. Notice that there is no comma between the table names. The parentheses around the join condition are optional. Finally, notice that the output is identical for both queries. For the rest of the examples in this chapter, we

Revised September 22, 2007 6 - 3

Page 4: Chapter06 Oracle

Chapter 6

interchangeably use both techniques so that you can learn to specify the join conditions in both the FROM and WHERE clauses.

/* SQL Example 6.4 - Query with alias names */SELECT LastName "Last Name", FirstName "First Name", DepartmentName "Department Name"FROM Employee e JOIN Department d ON (e.DepartmentNumber = d.DepartmentNumber)ORDER BY LastName, FirstName;

Last Name First Name Department Name--------------- --------------- ------------------------------Adams Adam Admin/LabsBarlow William Emergency-SurgicalBecker Robert Emergency-Surgicalmore rows will be displayed . . .

HOW JOINS ARE PROCESSEDHOW JOINS ARE PROCESSED

Now that you've seen a basic JOIN query, it's time to learn what SQL is doing for you behind the scenes. Conceptually, when two tables are joined, SQL creates a Cartesian product of the tables. A Cartesian product consists of all possible combinations of the rows from each of the tables. Therefore, when a table with 10 rows is joined with a table with 20 rows, the Cartesian product is 200 rows (10 x 20 = 200). For example, joining the employee table with eight rows and the department table with three rows will produce a Cartesian product table of 24 rows (8 x 3 = 24).

It is important to understand how JOIN queries are processed in order to develop your knowledge of this important concept. Therefore, we will examine a series of examples to aid you in understanding the JOIN operation process. Table 6.1 shows two tables simply named table_1 and table_2. Each table has a single column named col_1. Each table also has three rows with simple alphabetic values stored in the col_1 column.

Table 6.1

Table_1 Table_2Col_1 Col_1

======== ========A aB bC c

A Cartesian product of these tables yields a result table with nine rows (3 x 3 = 9). The query in SQL Example 6.5 that produces the Cartesian product is elementary.

/* SQL Example 6.5 */COLUMN col_1 FORMAT A5;SELECT *FROM Table_1, Table_2;

COL_1 COL_1----- -----a ab ac a

Revised September 22, 2007 6 - 4

Page 5: Chapter06 Oracle

Chapter 6

a bb bc ba cb cc c

An examination of the result table reveals that the first row of table_1 was joined with every row of table_2. Likewise, the second row of table_1 was joined with every row of table_2, and so forth.

A Cartesian product result table is normally not very useful. In fact, such a result table can be terribly misleading. If you execute this type of query for the employee and department tables, the result table implies that every employee has a relationship with every department, and we know that this is simply not the case!

The query in SQL Example 6.4 requires a JOIN in the FROM clause to specify the nature of the relationship between the two tables. This will prevent the error of joining rows that are not related. SQL Example 6.6 gives the revised query. The JOIN specifies that only related rows are to be displayed in the result table, in other words, where values in table_1 match the values in table_2.

/* SQL Example 6.6 */SELECT *FROM Table_1 t1 JOIN Table_2 t2 ON t1.col_1 = t2.col_1;

COL_1 COL_1----- -----a ab bc c

The JOIN filters out rows that are not related. Conceptually, it is important to understand that the JOIN specification is the key to joining tables. We will now return to SQL Example 6.4 that joins employee and department tables; however, we will now restrict the result table to a listing of employees that work in a specific department. The revised query shown in SQL Example 6.7 specifies the listing of employees in the Admin/Labs Department (department 8). Note that here the JOIN is accomplished with the FROM clause leaving the WHERE clause for use in specifying how the rows are to be filtered. You need to understand that a WHERE clause can JOIN tables as well as restrict the rows displayed in the result table based on specified criteria. This is illustrated by the SQL Example 6.8. The WHERE clause specifies the JOIN condition and uses the logical AND operator to specify a filtering condition. The result table for both SELECT statements is identical.

/* SQL Example 6.7 *//* Join conditions in the FROM clause */SELECT LastName "Last Name", FirstName "First Name", DepartmentName "Department Name"FROM Employee e JOIN Department d ON (e.DepartmentNumber = d.DepartmentNumber)WHERE e.DepartmentNumber = 8ORDER BY LastName, FirstName;

Last Name First Name Department Name

Revised September 22, 2007 6 - 5

Page 6: Chapter06 Oracle

Chapter 6

--------------- --------------- ------------------------------Adams Adam Admin/LabsBoudreaux Beverly Admin/LabsClinton William Admin/LabsSimmons Lester Admin/LabsThornton Billy Admin/Labs

/* SQL Example 6.8 *//* Join conditions in the WHERE clause */SELECT LastName "Last Name", FirstName "First Name", DepartmentName "Department Name"FROM Employee e, Department d WHERE e.DepartmentNumber = d.DepartmentNumber AND e.DepartmentNumber = 8ORDER BY LastName, FirstName;

JOIN OPERATION RULESJOIN OPERATION RULES

JOINS and the SELECT Clause

Now that you have seen several JOIN examples, we will review the detailed rules that you need to understand in order to produce successful JOIN operations. As with any query, a JOIN query always begins with a SELECT clause. List the columns to be displayed in the result table after the SELECT keyword. Further, the result table column order reflects the order in which column names are listed in the SELECT clause. If a manager wants the order of the columns modified, you simply rearrange the order of the column listing in the SELECT clause. SQL Example 6.9 moves the Department Name column to the first column position in the result table.

/* SQL Example 6.9 */SELECT DepartmentName "Department Name", LastName "Last Name", FirstName "First Name"FROM Employee e JOIN Department d ON (e.DepartmentNumber = d.DepartmentNumber)WHERE e.DepartmentNumber = 8ORDER BY LastName, FirstName;

Department Name Last Name First Name------------------------------ --------------- ---------------Admin/Labs Adams AdamAdmin/Labs Boudreaux BeverlyAdmin/Labs Clinton WilliamAdmin/Labs Simmons LesterAdmin/Labs Thornton Billy

JOIN operations also support the specification of all columns by the use of a simple asterisk (*) in a SELECT clause. The result table for such a query will contain all columns from the joined tables. When the asterisk (*) is used, the column order of the result table is based on the order in which tables are listed in the FROM clause.

Revised September 22, 2007 6 - 6

Page 7: Chapter06 Oracle

Chapter 6

JOINS and the FROM Clause

Any SELECT statement that has two or more table names (or view names—see Chapter 8) listed in a FROM clause is a JOIN query. By definition, a JOIN operation retrieves rows from two or more tables.

You can always use the FROM clause to list the tables from which columns are to be retrieved by a JOIN query, although it is unusual to join more than three or four tables in a single SQL statement. The order of table name listings is irrelevant to the production of the result table with the one exception noted above; that is, if you use an asterisk (*) in the SELECT clause, then the column order in the result table reflects the order in which tables are listed in the FROM clause.

As explained earlier, you can specify the join conditions in a FROM clause by explicitly using the JOIN clause within the FROM clause. You can also specify the type of JOIN such as INNER, LEFT OUTER, RIGHT OUTER, or FULL OUTER. If you do not specify the type of join then, by default, the join operation is always an INNER join. We did not indicate the type of join in any of the example queries thus far. So, they are all examples of INNER join operations. The various OUTER join operations are covered later in this chapter.

JOINS and the WHERE Clause

As you learned earlier, the WHERE clause can be used to specify the relationship between tables listed in the FROM clause along with specifying row selection criteria for display in the result table. For all practical purposes, you may specify as many selection criteria as are necessary to produce the desired result table. Additionally, although the queries shown thus far have always specified the JOIN operation before specifying selection criteria, the order of selection criteria or JOIN operations is not important..

Qualifying Column Names and Aliases

Normally, you do not need to create alias names for tables. This is optional. However, when column names are ambiguous, you must qualify the column names. A column name is ambiguous when the same column name is used in different tables. Review the earlier SQL Example 6.6 with the tables named Table_1 and Table_2. Note that the ON keyword within the FROM clause is:

FROM Table_1 t1 JOIN Table_2 t2 ON t1.col_1 = t2.col_1;

Since each table has a column named col_1, the column names used to accomplish the JOIN operation are qualified by referencing the table name, "dot," and the column name. If the column names are not qualified, Oracle will return the ORA-00918: column ambiguously defined error message. This error message tells you that you have included a column name somewhere in the query that exists in more than one table listed in the FROM clause.

It is also possible to make a similar error in the SELECT clause. The SELECT statement shown in SQL Example 6.10 fails to qualify the col_1 name in the SELECT clause, and Oracle again produces the ORA-00918 error message.

/* SQL Example 6.10 */SELECT col_1FROM Table_1 t1 JOIN Table_2 t2

Revised September 22, 2007 6 - 7

Page 8: Chapter06 Oracle

Chapter 6

ON t1.col_1 = t2.col_1;

ERROR at line 1:ORA-00918: column ambiguously defined

As you have seen, an ambiguous column name is qualified by using the DOT ( .) connector to connect the table name and column name. Sometimes, it is easier to qualify column names by using table alias names. As was demonstrated earlier, a table can be assigned an alias name for a query by simply listing a unique identifier for the table name in the FROM clause. Often, a single letter is used as an identifier to reduce keystroke requirements as was done earlier in the JOIN query for the employee and department tables shown here as SQL Example 6.11.

/* SQL Example 6.11 */SELECT LastName "Last Name", FirstName "First Name", DepartmentName "Department Name"FROM Employee e JOIN Department d ON (e.DepartmentNumber = d.DepartmentNumber)WHERE e.DepartmentNumber = 8ORDER BY LastName, FirstName;

The use of the letters "e" and "d" is completely arbitrary; "t1" and "t2" or any other unique aliases could be used. The important points to learn are:

The alias name must follow a table name. Use a space to separate a table name and its alias name. The alias name must be unique within the SELECT statement.

When column names are not identical you are not required to qualify them. Sometimes, they are qualified anyway because it can be helpful in terms of documenting the query. The query in SQL Example 6.11 can be documented by rewriting it as is shown in SQL Example 6.12. In this fashion, it becomes clear that the DepartmentName column is retrieved from the department table. Likewise, the LastName and FirstName columns are retrieved from the employee table.

/* SQL Example 6.12 */SELECT e.LastName "Last Name", e.FirstName "First Name", d.DepartmentName "Department Name"FROM Employee e JOIN Department d ON (e.DepartmentNumber = d.DepartmentNumber)WHERE e.DepartmentNumber = 8ORDER BY LastName, FirstName;

While not required by the database management system processing the SQL statement, additional column qualification may help you and future programmers decipher the query should it ever need to be modified.

JOIN—Relational Operators

The JOIN operators shown in Table 6.2 determine the basis by which columns are matched and are called relational operators. You will recognize them as the comparison operators that you learned earlier.

Revised September 22, 2007 6 - 8

Page 9: Chapter06 Oracle

Chapter 6

Table 6.2

Operator Meaning= equal to < less than> greater than

>= greater than or equal to<= less than or equal to!= not equal to<> not equal to !> not greater than!< not less than

Additional WHERE Clause Options

Thus far, we have studied some examples that use the WHERE clause to both join tables and to specify simple selection criteria, such as the specification of a certain department number for row selection. In fact, all of the selection criteria used in earlier chapters to add power to queries can also be used with JOIN operations. SQL Example 6.13 gives a SELECT statement that retrieves the names of employees based on department numbers by using the IN operator to select employees in either department 3 (Emergency-Surgical) or 7 (Pharmacy Department).

/* SQL Example 6.13 *//* Join condition in the WHERE clause */SELECT LastName "Last Name", FirstName "First Name", DepartmentName "Department Name"FROM Employee e, Department dWHERE e.DepartmentNumber = d.DepartmentNumber AND d.DepartmentNumber IN (3, 7)ORDER BY LastName;Last Name First Name Department Name--------------- --------------- ------------------------------Barlow William Emergency-SurgicalBecker Robert Emergency-SurgicalBoudreaux Betty Pharmacy DepartmentJones Quincey Emergency-SurgicalSmith Susan Emergency-SurgicalSumner Elizabeth Emergency-Surgical

6 rows selected.

For all practical purposes, you may specify as many selection criteria as is necessary to produce the desired result table. Additionally, although the queries shown thus far have always specified the JOIN operation first, the order of selection criteria or JOIN operations is not important. Query 6.13 could have been rewritten as is shown in SQL Example 6.14. Notice that the criteria for row selection and table joins in the WHERE clause are reversed, as is the department number listing within the IN listing.

/* SQL Example 6.14 */SELECT LastName "Last Name", FirstName "First Name", DepartmentName "Department Name" FROM Employee e, Department d

Revised September 22, 2007 6 - 9

Page 10: Chapter06 Oracle

Chapter 6

WHERE d.DepartmentNumber IN (7, 3) AND e.DepartmentNumber = d.DepartmentNumberORDER BY LastName;

JOIN Operations Using Inequality Operators (<, >, <>)

The JOIN queries covered thus far are termed equijoins because the relational operator used in the JOIN operation is the equal sign (=). However, you may use any relational operator in a JOIN query. This query in SQL Example 6.15 uses an inequality operator, the not equal to than (<>) relational operator.

/* SQL Example 6.15 *//* Join condition in the FROM clause */COLUMN "Dependent Name" FORMAT A15;SELECT LastName "Last Name", Name "Dependent Name"FROM Employee e JOIN Dependent d ON e.EmployeeID <> d.EmployeeIDWHERE e.LastName IN ('Bordoloi', 'Bock')ORDER BY LastName;

Last Name Dependent Name--------------- ---------------Bock AnitaBock MitaBock MonicaBock RitaBock AllenBock AndrewBock Jo EllenBock SusanBordoloi DeannaBordoloi JefferyBordoloi Mary EllenBordoloi MichelleBordoloi RachaelBordoloi AllenBordoloi AndrewBordoloi Jo EllenBordoloi Susan17 rows selected.

Query 6.15 produces a result table in which the dependent names listed are not dependents of the respective employees who are listed. Note that Jo Ellen, Andrew, Allen, and Susan are not dependents of either employee, and so these four dependents are listed twice. The query may not make a lot of sense to you as an SQL programmer, but its usefulness depends on management's need for the information.

As it happens, JOIN operations using inequality operators are not used very often. Most queries are equijoins because a JOIN operation based on equality often make the most sense. Conceptually, a JOIN operation involving an inequality operator works the same way as an equijoin. A Cartesian product is formed from the employee and dependent tables. The result table is then populated based on the inequality JOIN condition and selection criteria.

Revised September 22, 2007 6 - 10

Page 11: Chapter06 Oracle

Chapter 6

COMPLEX JOIN OPERATIONSCOMPLEX JOIN OPERATIONS

While the examples given thus far have joined rows from two tables, you can specify up to 16 tables in a JOIN operation. Sixteen is a very large number! While it is not uncommon to have three or four tables in a JOIN operation, it would be very unusual to exceed this number; thus, it turns out that 16 is not much of a limitation. You do need to understand that the more tables that are included in a JOIN operation, the longer the query will take to process, especially when the tables are large with millions of rows per table.

Joining Three Tables

The example shown in Figure 6.2 joins three tables to produce a result table based on two different relationships. The bold lines show that the projectAssignment table is related to the employee table through the EmployeeID column's domain of values. Similarly, the projectAssignment table is related to the project table through the ProjectNumber column's domain of values.

Figure 6.2

The projectAssignment table is classified as an association table because the rows in it relate to or associate both the employee and project tables simultaneously. An association table relates or associates two or more other tables where the other tables would be related in a many-to-many fashion. Here, the projectAssignment table depicts the fact that many employees can be assigned to work on a project, and a project can simultaneously have many employees assigned to it; thus, the relationship between employee and project is many-to-many. A many-to-many relationship is implemented by decomposing it into two one-to-many relationships as shown in this figure. The primary key of the projectAssignment table is a composite of EmployeeID + ProjectNumber. Association tables are also termed intersection or conjunction tables.

The SELECT statement to join the tables depicted in Figure 6.2 is shown in SQL Example 6.16. A FROM clause is used to join the three tables. A WHERE clause filters the result table rows to only those rows that have a project title of 'Child Care Center.'

/* SQL Example 6.16 *//* Join conditions in the FROM clause */

Revised September 22, 2007 6 - 11

Page 12: Chapter06 Oracle

Chapter 6

COLUMN "Raised Salary" FORMAT $999,999;SELECT LastName "Last Name", FirstName "First Name", 1.10*Salary "Raised Salary", p.ProjectTitle "Project"FROM Employee e JOIN ProjectAssignment a ON (e.EmployeeID = a.EmployeeID) JOIN Project p ON (a.ProjectNumber = p.ProjectNumber)WHERE p.ProjectTitle LIKE 'Child Care Center';

Last Name First Name Raised Salary Project--------------- --------------- ------------- -------------------------Eakin Maxwell $16,500 Child Care CenterAdams Adam $6,050 Child Care CenterSimmons Lester $24,200 Child Care Center

This is a good example of a situation in which joining more than two tables yields information that managers may find extremely helpful. The result table shown provides information about what employee salaries will be if every employee on the 'Child Care Center' project is given a 10 percent raise.

Let's take a closer look at the query in SQL Example 6.16. This may seem strange, but did you notice that the projectAssignment table does not contribute any columns to the result table! Also none of the columns used to specify the JOIN operation are included in the result table. Even when are not represented in a result table, table columns may be used to formulate a join operation.

Examine Figure 6.2 again. The bold lines connecting the tables depict the fact that the JOIN operation involves two different conditions that are stated in query 6.16. The first condition joins the employee and projectAssignment tables based on each employee's EmployeeID. Thus, only employees who are working on a project are included in the result table. The second condition joins the projectAssignment and project tables based on the ProjectNumber columns in each table. This means that only projects that have associated rows in the projectAssignment table will be included in the result table.

e.EmployeeID = a. EmployeeID /* Condition #1 */ a.ProjectNumber = p.ProjectNumber /* Condition #2 */ p.ProjectTitle LIKE 'Child Care Center'; /* Condition #3 */

Finally, there is a third condition in the WHERE clause. The third condition does not join any tables; rather, it specifies criteria for row selection in order to restrict the result table to those rows for employees working on the 'Child Care Center' project. Conceptually, a Cartesian product of the three tables is formed, and then only those rows satisfying the conditions stated in the WHERE clause are retained for the result table.

SQL Example 6.17 is a revision of SQL Example 6.16. Here the join conditions are specified using WHERE clause syntax.

/* SQL Example 6.17 *//* Join conditions in the WHERE clause */COLUMN "Raised Salary" FORMAT $999,999;SELECT LastName "Last Name", FirstName "First Name", 1.10*Salary "Raised Salary", p.ProjectTitle "Project"FROM Employee e, ProjectAssignment a, Project pWHERE e.EmployeeID = a. EmployeeID AND a.ProjectNumber = p.ProjectNumber AND p.ProjectTitle LIKE 'Child Care Center';

Revised September 22, 2007 6 - 12

Page 13: Chapter06 Oracle

Chapter 6

Last Name First Name Raised Salary Project--------------- --------------- ------------- -------------------------Eakin Maxwell $16,500 Child Care CenterAdams Adam $6,050 Child Care CenterSimmons Lester $24,200 Child Care Center

Last Name First Name Raised Salary Project--------------- --------------- ------------- -------------------------Eakin Maxwell $16,500 Child Care CenterAdams Adam $6,050 Child Care CenterSimmons Lester $24,200 Child Care Center

Have you determined yet that the two tables, employee and project, are not directly joinable as they do not have any direct relationship represented by a ‘primary–foreign key’ relationship. A typical join condition specifies a foreign key from one table and its associated primary key in the other table. To display data from tables linked through an association table, you may need to join three or four or even more tables. Note, however, that you can join only two tables at a time. This should be clear in SQL Example 6.17 because of the syntax when using the JOIN keyword, that is, you can have only two table names in each join condition. Thus, if you are joining two tables then you must have at least one join condition; if you are joining three tables then you must have at least two join conditions; and if you are joining n tables, then you must have at least n − 1 join conditions.

Joining Four Tables

Figure 6.3 depicts what is termed a ternary relationship. Some textbooks on database modeling may also term this type of relationship a gerund. A ternary relationship is a relationship among three base tables (employee, patient, and service) at the same time, and it is implemented by creating three one-to-many relationships where the three base tables are related to a single association table (treatment) by creating foreign key columns in the association table.

Study Figure 6.3. This relationship represents the storage of information about which service (identified by ServiceID) was provided by which employee (identified by EmployeeID) to which patient (identified by PatientID). Many different services can be provided by many different employees to many different patients. For example, an appendectomy or tonsillectomy can be provided by Dr. Bordoloi or Dr. Bock to patient Smith or patient Jones.

The treatment association table has a composite primary key identifier of TreatmentNumber and TreatmentDate along with three foreign key columns, ServiceID, EmployeeID, and PatientID as links to reference data rows in the three base tables. The TreatmentDate column is included as part of the composite primary key because the same service may be provided by the same employee to the same patient on many different days and times. The chief of physicians may require a report listing the names of patients receiving treatment where the result table displays the patient name, service description, and employee names as well as the date on which the service was provided by Dr. Quattromani. This requires a join operation that joins the four tables.

Revised September 22, 2007 6 - 13

Page 14: Chapter06 Oracle

Chapter 6

Figure 6.3

SQL Example 6.18 gives two SELECT statements – the first joins the tables through use of the FROM clause with the JOIN key word while the second shows the WHERE clause syntax. Both examples produce the same result table. The use of the two vertical double-bars (| |) is Oracle's concatenation operator used to add character strings to form a single character string. Here the patient's LastName and FirstName columns are concatenated along with a separating comma and blank space.

/* SQL Example 6.18 *//* Join conditions in the FROM clause */COLUMN "Patient Name" FORMAT A25;COLUMN "Treatment" FORMAT A20;COLUMN "Med Employee" FORMAT A15;SELECT p.LastName || ', ' || p.FirstName "Patient Name", s.Description "Treatment", e.LastName "Med Employee"FROM Patient p JOIN Treatment t ON (p.PatientID = t.PatientID) JOIN Employee e ON (e.EmployeeID = t.EmployeeID) JOIN Service s ON (s.ServiceID = t.ServiceID)WHERE e.LastName = 'Quattromani' ORDER BY p.LastName, p.FirstName;

/* Join conditions in the WHERE clause */SELECT p.LastName || ', ' || p.FirstName "Patient Name", s.Description "Treatment", e.LastName "Med Employee"FROM Patient p, Employee e, Treatment t, Service sWHERE p.PatientID = t.PatientID AND e.EmployeeID = t.EmployeeID AND s.ServiceID = t.ServiceID AND e.LastName = 'Quattromani' ORDER BY p.LastName, p.FirstName;

Patient Name Treatment Med Employee------------------------- -------------------- ---------------

Revised September 22, 2007 6 - 14

Page 15: Chapter06 Oracle

Chapter 6

Ridgeway, Ricardo EKG/Interp QuattromaniRidgeway, Ricardo Therapeutic Inj Quattromani

Note the join conditions in SQL Example 6.18. Each base table (service, staff, and patient) is joined to the treatment association table by setting the primary key column from each base table equal to the associated FK column in treatment, for example:

FROM Patient p JOIN Treatment t ON (p.PatientID = t.PatientID) /* condition 1 */

The WHERE version of the query joins the tables and specifies the search criteria in the WHERE clause through liberal use of the AND operator. You may find the syntax that uses the WHERE clause to be easier to understand than the query that uses the JOIN keyword; still the use of the JOIN keyword is the current ANSI/ISO-92 standard for SQL.

Joining Tables by Using Two Columns

Study the diagram in Figure 6.4. This diagram depicts the relationship at a university where students enroll in course sections.

Figure 6.4

The enrollment table stores rows describing enrollments in various course sections and is identified by a composite key that includes the student SSN, course number, and section number columns. The section table stores information about sections of courses that are offered in a given term, and has rows identified by a composite key that includes the course number and section number. In order to join the enrollment and section tables, the JOIN operation needs to specify a complex JOIN condition that includes both the CourseNumber and SectionNumber columns from both tables. This is because neither the CourseNumber nor SectionNumber columns are sufficient by themselves to identify the associated rows for a given course and section. This example can be extended to three or more columns and to three or more tables.

The SELECT statement that accomplishes the JOIN based on two columns is shown in SQL Example 6.19. Again, this situation arises when the related tables have composite primary key columns. You may recall that a composite primary key is required when a single column is not sufficient to guarantee the unique identification of table rows.

/* SQL Example 6.19 *//* Join conditions in the WHERE clause */SELECT s.CourseNumber "Course", e.StudentSSN "Student SSN", s.RoomLocation "Room"FROM Enrollment e, Section sWHERE e.CourseNumber = s.CourseNumber AND

Revised September 22, 2007 6 - 15

Page 16: Chapter06 Oracle

Chapter 6

e.SectionNumber = s.SectionNumber;

/* Join conditions in the FROM clause */SELECT s.CourseNumber "Course", e.StudentSSN "Student SSN", s.RoomLocation "Room"FROM Enrollment e JOIN Section s ON (e.CourseNumber = s.CourseNumber) AND (e.SectionNumber = s.SectionNumber);

OUTER JOIN OPERATIONSOUTER JOIN OPERATIONS

The type of JOIN you have been exposed to thus far is an INNER JOIN, more specifically an equijoin where tables are joined based on equality of values in common columns. This is what most people refer to when they use the term JOIN. There is, however, another class of join operations called OUTER JOINs. This type of join has a limited, but very important and specific purpose. It is used to identify situations where rows in one table do not match rows in a second table, even though the two tables are related.

Such would be the situation if management wants to know what products are available but have never been sold to a customer. Clearly, management would want to eliminate the stockage of poorly selling products. Typically a name named product (or a similar name) stores data rows about all products a firm stocks for sale while a sales table stores rows only about products that have actually sold. If a product is not listed in the sales table, then it has not sold although there will be a data row for the product in the product table. An OUTER JOIN of product on sales allows rows from the product table to appear in a result table even when there are no matching values in the sales table to which it is joined.

Types of OUTER JOIN

There are three types of outer joins: the LEFT, RIGHT, and FULL OUTER JOIN. They all begin with an INNER JOIN, and then they add back some of the rows that have been dropped. A LEFT OUTER JOIN adds back all the rows that are dropped from the first (left) table in the join condition, and output columns from the second (right) table are set to NULL. A RIGHT OUTER JOIN adds back all the rows that are dropped from the second (right) table in the join condition, and output columns from the first (left) table are set to NULL. The FULL OUTER JOIN adds back all the rows that are dropped from both the tables. We do not address the FULL OUTER JOIN in this text.

Let's examine an OUTER JOIN situation for the Madison Hospital database. Suppose management needs a listing of all employees of the firm as well as their dependents. Figure 6.5 shows the relationship between the employee and dependent tables. The EmployeeID column is a primary key in the dependent table that also serves as a foreign key as it has a shared domain with the EmployeeID column of the employee table. Each dependent has a single employee to whom they belong. Employees may have one or more dependents; however, some employees will not have any dependents. This is analogous to the product sales situation described above since some products have no sales history. We can use an OUTER JOIN to join the employee and dependent tables even when employees have no dependents.

The query in SQL Example 6.20 produces the desired result table. The first SELECT statement uses the LEFT OUTER JOIN keywords in the FROM clause. The second SELECT statement gives the LEFTOUTER JOIN in the WHERE clause. The plus sign in parentheses (+) in the second SELECT statement tells Oracle to execute an OUTER JOIN operation. In fact, this

Revised September 22, 2007 6 - 16

Page 17: Chapter06 Oracle

Chapter 6

is a LEFT OUTER JOIN because the query will return ALL of the rows from the employee table that is listed on the left side of the join operation in the WHERE clause. The plus symbol (+) is on the right-side of the equal sign indicating that some values of EmployeeID for the dependent table will be NULL – no dependent corresponding to the employee. The naming of the LEFT OUTER JOIN may seem backwards, but it is the dependent table (right side) that is being outer-joined to the employee table (left side) because some employees will not have dependents.

Figure 6.5

/* SQL Example 6.20 *//* Join conditions in the FROM clause */COLUMN "Dependent" FORMAT A14;COLUMN "Relationship" FORMAT A12;SELECT LastName "Last Name", FirstName "First Name", Name "Dependent", RelationshipToEmployee "Relationship"FROM Employee e LEFT OUTER JOIN Dependent d ON (e.EmployeeID = d.EmployeeID);

/* Join conditions in the WHERE clause */SELECT LastName "Last Name", FirstName "First Name", Name "Dependent", RelationshipToEmployee "Relationship"FROM Employee e, Dependent dWHERE e.EmployeeID = d.EmployeeID(+);

Last Name First Name Dependent Relationship--------------- --------------- -------------- ------------Bock Douglas Jeffery SONBock Douglas Deanna DAUGHTERBock Douglas Michelle DAUGHTERBock Douglas Mary Ellen SPOUSEBock Douglas Rachael DAUGHTERSumner ElizabethBordoloi Bijoy Mita SPOUSEBordoloi Bijoy Monica DAUGHTERBordoloi Bijoy Rita DAUGHTERBordoloi Bijoy Anita DAUGHTEREakin Maxwellmore rows will display . . .

Revised September 22, 2007 6 - 17

Page 18: Chapter06 Oracle

Chapter 6

The result table lists some employees more than once. This happens when an employee has more than one dependent. Also, some employees do not have any dependents listed. The Name and RelationshipToEmployee columns of these employees are NULL and display as missing values in the result table.

You need to understand that Oracle recommends coding OUTER JOIN operations through use of the FROM clause as opposed to use of the (+) join operator in a WHERE clause. This is because there are several restrictions on the use of the (+) operator while there are no restrictions on OUTER JOIN operations coded through use of the FROM clause.

OUTER JOINS and NULL Values

The result table produced by SQL Example 6.20 is useful, but what if your manager wants the listing of employees to be restricted to list only employees who do not have any dependents. Again, this is analogous to the sales order situation described earlier in which it might be advantageous to produce a listing of only products that have never sold. This would enable our firm to advertise those products and to get them off of our store's shelves. Similarly, management might desire a listing of employees with no dependents in order to satisfy some governmental reporting requirement.

Now, you may argue that for the small number of rows given in our result table, a manager could manually "line through" any employees that have dependents and obtain the required information. However, if the result table is large, most managers would find this approach to be unacceptable.

We can take advantage of the fact that the Name column will be NULL for employees with no dependents, and simply add a criteria to the WHERE clause to exclude employees where the Name column is NULL. Additionally, we can tidy up the result table by eliminating the dependent and relationship columns as output since they will be blank. We simply remove these column names from the SELECT clause listing. SQL Example 6.21 produces a clean result table that provides only the essential information needed by management.

/* SQL Example 6.21 */SELECT LastName || ', ' ||FirstName "Employees Without Dependents" FROM Employee e LEFT OUTER JOIN Dependent d ON (e.EmployeeID = d.EmployeeID)WHERE d.Name IS NULL;

Employees Without Dependents-------------------------------Sumner, ElizabethEakin, MaxwellWebber, Eugenemore rows will display . . .

LEFT and RIGHT OUTER JOIN Operations

Eventually, as your career as an SQL programmer blossoms, you will hear arguments about the terms RIGHT OUTER JOIN and LEFT OUTER JOIN. These terms refer to ordering of the tables depicted in an entity-relationship diagram. Earlier, we noted that the OUTER JOIN between the employee and dependent tables is a LEFT OUTER JOIN. However, if the employee table were to be depicted on the right side of the relationship in Figure 6.5, and if it is outer-

Revised September 22, 2007 6 - 18

Page 19: Chapter06 Oracle

Chapter 6

joined with a dependent table depicted on the left side of the relationship, this is sometimes referred to as a RIGHT OUTER JOIN.

Now if you think about it, the entity-relationship diagram could just as easily have been drawn with the dependent table on the left and the employee table on the right. Does the fact that this is now called a RIGHT OUTER JOIN make any difference to SQL? The answer is no. The query in SQL Example 6.21 can be rewritten as a RIGHT OUTER JOIN as given in SQL Example 6.22. Can you find the slight difference? We have highlighted it for you. The + is now shown on the left side of the equal sign, but the query is still returning ALL of the rows from the employee table. The query has the order of the conditions in the JOIN operation reversed from their earlier specification. Regardless, SQL dutifully produces exactly the same result table!

/* SQL Example 6.21 */SELECT LastName || ', ' ||FirstName "Employees Without Dependents" FROM Dependent d RIGHT OUTER JOIN Employee e ON (d.EmployeeID = e.EmployeeID)WHERE d.Name IS NULL;

Employees Without Dependents-------------------------------Sumner, ElizabethEakin, MaxwellWebber, Eugenemore rows will display . . .

So remember, if a colleague wants to "quibble" about whether a JOIN operation is a LEFT versus RIGHT OUTER JOIN, the difference is purely semantic.

SELF-JOIN OPERATIONSSELF-JOIN OPERATIONS

A SELF-JOIN operation produces a result table when the relationship of interest exists among rows that are stored within a single table. This is the case for the company's employee table for the supervise relationship depicted in Figure 6.6. Each employee is identified by the EmployeeID column value. If the employee has a supervisor, their SupervisorID column will store the employee identifying number of the supervisor. Thus, the supervise relationship is implemented through the SupervisorID column. EmployeeID and SupervisorID columns have a common domain of values. A supervisor is simply an employee who performs supervisory functions, and so we did not create a separate table to store supervisor rows. If you study the data for the employee table, you will discover that the employee who is in charge of the company has a NULL value for the SupervisorID column.

The query in SQL Example 6.22 produces a listing of employees and their supervisors. The SELECT clause concatenates each supervisor's last and first names along with a comma separator between names into a single output column. This is also done for employees who are supervised.

The FROM clause specifies the employee table twice, each time with a different table alias name (e1 and e2). This is necessary in order to create a Cartesian product between what appear to be two different and separate employee tables named e1 and e2. The alias table names are used to specify the SELF-JOIN operation in the WHERE clause. Rows are joined where the EmployeeID of one employee table row equals the SupervisorID of another employee table row.

Revised September 22, 2007 6 - 19

Page 20: Chapter06 Oracle

Chapter 6

Figure 6.6

/* SQL Example 6.22 */COLUMN "Employee" FORMAT A28;COLUMN "Supervisor" FORMAT A28;SELECT e1.LastName || ' ' || e1.FirstName "Supervisor", e2.LastName || ' ' || e2.FirstName "Employee"FROM Employee e1 JOIN Employee e2 ON (e1.EmployeeID = e2.SupervisorID)ORDER BY e2.SupervisorID DESC;

Supervisor Employee---------------------------- ----------------------------Becker Roberta Brockwell Mary EllenBecker Roberta Young YvonneBecker Roberta Simmons LeslieSimmons Lester Boudreaux BeverlySimmons Lester Eakin MaxwellSimmons Lester Becker RobertaSimmons Lester Sumner ElizabethSimmons Lester Webber EugeneSimmons Lester Klepper RobertKlepper Robert Zumwalt MaryKlepper Robert Quattromani Tonimore rows will display . . .

The result table is sorted by SupervisorID – some employees supervisor more than one other employee as would be expected. Did you notice that one row is missing from the result table? This is the row for employee Lester Simmons because he has no supervisor. He is in charge of the company and, as was noted earlier, the SupervisorID column value for Simmons' row is NULL. If we wish to produce a complete listing of employees including Simmons, we can execute a self-RIGHT OUTER JOIN, as is done in SQL Example 6.30. The result table shows a blank value the Supervisor column for Simmons.

/* SQL Example 6.30 */SELECT e1.LastName || ' ' || e1.FirstName "Supervisor", e2.LastName || ', ' || e2.FirstName "Employee"FROM Employee e1 RIGHT OUTER JOIN Employee e2

Revised September 22, 2007 6 - 20

Page 21: Chapter06 Oracle

Chapter 6

ON (e1.EmployeeID = e2.SupervisorID)ORDER BY e2.SupervisorID DESC;

Supervisor Employee---------------------------- ---------------------------- Simmons, LesterBecker Roberta Young, YvonneBecker Roberta Simmons, LeslieBecker Roberta Brockwell, Mary EllenSimmons Lester Becker, RobertaSimmons Lester Klepper, Robertmore rows will display . . .

NATURAL JOINNATURAL JOIN

The NATURAL keyword can simplify the syntax of an equijoin. A NATURAL JOIN is possible whenever two (or more) tables have columns with the same name, and the columns are join compatible, i.e., the columns have a shared domain of values. The join operation joins rows from the tables that have equal column values for the same named columns.

Consider the one-to-many relationship between the department and project tables. Each table has a column named DepartmentNumber. This column is the primary key of the department table and a foreign key of the project table. SQL Example 6.31 uses a NATURAL JOIN query to list the department number, department name, and project title for projects managed by department number 6. The syntax is simpler than a join that has the join condition specified with the ON keyword – here the Oracle server simply joins the tables based on two DepartmentNumber columns with the same name.

/* SQL Example 6.31 */COLUMN "Dept #" FORMAT 999999;COLUMN "Department" FORMAT A25;COLUMN "Project" FORMAT A25;SELECT DepartmentNumber "Dept #", d.DepartmentName "Department", p.ProjectTitle "Project"FROM Department d NATURAL JOIN Project pWHERE DepartmentNumber = 6;

Dept # Department Project------- ------------------------- ------------------------- 6 Pediatrics-Gynecology New Pediatric Monitors 6 Pediatrics-Gynecology Child Care Center

Compare SQL Example 6.31 to SQL Example 6.32. SQL Example 6.32 joins the two tables by explicitly specifying the join condition with the ON keyword.

/* SQL Example 6.32 */SELECT DepartmentNumber "Dept #", d.DepartmentName "Department", p.ProjectTitle "Project"FROM Department d JOIN Project p ON (d.DepartmentNumber = p.DepartmentNumber)WHERE DepartmentNumber = 6;

Dept # Department Project------- ------------------------- ------------------------- 6 Pediatrics-Gynecology New Pediatric Monitors

Revised September 22, 2007 6 - 21

Page 22: Chapter06 Oracle

Chapter 6

6 Pediatrics-Gynecology Child Care Center

There are some limitations regarding the NATURAL JOIN. You cannot specify a LOB column with a NATURAL JOIN. Also, columns involved in the join cannot be qualified by a table name or alias. SQL Example 6.33 shows the Oracle error message generated if you make the mistake of trying to qualify the DepartmentNumber column in either the SELECT, FROM, WHERE, or other clause of the command.

/* SQL Example 6.33 */SELECT d.DepartmentNumber "Dept #", d.DepartmentName "Department", p.ProjectTitle "Project"FROM Department d NATURAL JOIN Project pWHERE DepartmentNumber = 6;

ERROR at line 1:ORA-25155: column used in NATURAL join cannot have qualifier

You can make other mistakes when using a NATURAL JOIN. Joins that involve more than two tables can be interpreted ambiguously. Consider this example where three tables are joined.

FROM TableA NATURAL JOIN TableB b JOIN TableC c ON b.Col1 = c.Col1

You can avoid the ambiguity by using parentheses to indicate early which tables are to be paired in a join. If you do not specify parentheses, Oracle will pair the tables from left to right. In this FROM clause, parentheses make clear that TableA is to be joined with TableB, the result of which is then joined with TableC.

FROM (TableA NATURAL JOIN TableB b) JOIN TableC c ON b.Col1 = c.Col1

There is another potential problem with the NATURAL JOIN. Consider a situation where management needs a listing of current managers by name for the different departments. A NATURAL JOIN of the department and employee tables causes the two tables to be joined based on the DepartmentNumber. However, such a join yields multiple rows for each department when there should clearly be just a single row per department as there is a single manager per department. Instead, the two tables should be joined on the employee.EmployeeID and department.ManagerID columns.

SUMMARYSUMMARY

In this chapter, you learned to write queries to display information that is extracted from related tables. You can use the WHERE clause to produce JOIN operations for up to 16 tables at a time, although two, three, or four tables are more common. A join of more than two tables requires the WHERE clause to include a complex JOIN condition that uses the AND logical operator. You also learned how to join two or more tables that have composite primary keys. You examined how to use the OUTER JOIN operation to produce queries where tables have rows that may or may not be related to rows in other tables. You learned how to use a SELF-JOIN operation to join rows from a table that are related to rows in the same table. Finally, you learned the syntax for a NATURAL JOIN as an alternative syntax for an equijoin. After completing the exercises in the review section that follows, you will have mastered the basic

Revised September 22, 2007 6 - 22

Page 23: Chapter06 Oracle

Chapter 6

concepts associated with joining tables. You should now have a basic understanding of the process that Oracle uses to execute a join query.

REVIEW EXERCISESREVIEW EXERCISES

Learn These Terms

1. Alias name—a shorthand method for referring to a table in order to simplify query writing.2. Ambiguous column names—occurs when two tables have columns named with identical

names. The column names must be qualified.3. Association table—a table that relates or associates two other tables where the relationship

between those two other tables would be many-to-many.4. Cartesian product—a result table consists of all possible combinations of the rows from

each of the tables. 5. Common column—another term for a foreign key in a table.6. Composite primary key—when a table is identified uniquely by more than one column

because a single column is not sufficient to guarantee uniqueness.7. Concatenate operator—two vertical bars ( | | ) used to concatenate two or more column

values or literals for display as a single column. 8. Domain—a specified set of values that are valid for store in a column of a database table.9. Equijoin—a JOIN operation that uses an equal sign as the relational operator.10. Foreign key—a column used to link a table to another related table. It may also be an

internal link within the table used to link rows with other related rows.11. JOIN—an operation used to connect (link) two or more tables based on a common domain

of values stored to common columns or foreign key columns.12. OUTER JOIN operation—allows rows from one table to appear in a result table even if

there is no matching value in the table to which it is joined. 13. SELF-JOIN operation—a JOIN that produces a result table when the relationship of

interest exists among rows that are stored within a single table.

Concepts Quiz

1. Explain the concept of a domain of values, and relate this concept to JOIN operations.2. Which clause in a SELECT statement is used to JOIN tables, and how is this typically

accomplished?3. What is an alias table name? Is it optional or mandatory?4. What is a Cartesian product? Why is it important?5. What specifies the order by which columns are displayed in a result table produced by a JOIN

operation in which only specified columns are selected?6. What specifies the order by which columns are displayed in a result table produced by a JOIN

operation in which all columns are selected through use of an asterisk (*) in the SELECT clause?

7. You have written a query that fails to execute. The Oracle Server returns the following error message. What do you need to do to correct the error condition?

ORA-00918: column ambiguously defined

8. You need to qualify a column named EmployeeID that is stored in both the employee and benefits tables. How do you refer to this column in a WHERE clause that has no alias names?

Revised September 22, 2007 6 - 23

Page 24: Chapter06 Oracle

Chapter 6

9. Assume that the alias names for the employee and benefits tables referenced in question 8 above are “e” and “b,” respectively. Now how would you reference the ambiguous EmployeeID columns?

10. Why would you qualify column names that are NOT ambiguous?11. What is the limit on using different selection criteria in the WHERE clause of a SELECT

statement that is joining tables?12. What is an equijoin as opposed to an inequality join?13. What is the maximum number of tables that can be listed in a JOIN operation?14. What is an association table? 15. When would your JOIN query have to join two or more tables by using more than one

column from each table in the JOIN condition?16. What is an OUTER JOIN? 17. Suppose that our firm tracks repair parts inventory in a table named inventory and the use of

those parts in a second table named partsUsed. What type of JOIN would be used to produce a listing of parts that have not been used and how would the JOIN operation conceptually produce the listing?

18. Continuing the situation described in question 17, suppose that some parts are manufactured by using other parts from inventory; thus, there is a relationship among the rows within the inventory table. What type of JOIN would be used to produce a listing of which parts are used to manufacture other parts?

SQL Coding Exercises and Questions

In answering the SQL exercises and questions, submit a copy of each command that you execute and any messages that Oracle generates while executing your SQL commands. Also list the output for any result table that is generated by your SQL statements.

1. Write a query to produce a result table that is a Cartesian product of the bed and bedClassification tables. The result table should include the BedNumber and Availability columns from bed and the Description column from bedClassification. How many rows are in the result table? List only the first five rows of the result table in your lab report.

2. The Cartesian product produced in question 1 is not terribly useful. Alter the query for question 1 to restrict row output by joining the two tables on the BedType column of each table. Write two queries, one that joins the tables with the FROM clause and one that joins the tables with the WHERE clause. Do not sort the output. How many rows are in the result table? List only the first five rows of the result table in your lab report.

3. The manager in the human resources department needs a listing of department managers, their salaries, and their assigned parking spaces. The query must display the DepartmentNumber, DepartmentName, FirstName and LastName (concatenate the name columns into a single column), Salary and ParkingSpace column values. Name the columns in the result table as follows: Dept., Department, Manager, Salary, and Parking, respectively. Sort the result table by DepartmentNumber. Use the FROM clause to join the tables. Use COLUMN-FORMAT commands to product a listing that fits easily on one page.

4. The company's vice president for project management needs a listing of projects that are supervised by each department. The result table needs to display the department name (DepartmentName), project number (ProjectNumber), project name (ProjectTitle), and project location (Location). Use the department and project tables and assign each output column an appropriate column name. Use the FROM clause to join the tables.

Revised September 22, 2007 6 - 24

Page 25: Chapter06 Oracle

Chapter 6

5. Rewrite the query for question 4 to restrict output to projects located in Alton or Edwardsville. Use the FROM clause to join the tables.

6. Rewrite the query for question 5 by using the WHERE clause to join the tables.7. The company's vice president for project management needs a listing of employees assigned

to projects. The result table should list the employee table LastName and FirstName column values (concatenated into one column) and their associated ProjectNumber and HoursWorked columns from the projectAssignment table. The result table should only list employees assigned to a project. Use alias names for the table names. Give each column an appropriate column name. Sort the output by LastName and FirstName. Use the FROM clause to join the tables. List only the first 10 rows of the result table in your lab report, but also list the number of rows selected by your query. Which employees are assigned to a project, but have not worked any hours on a project?

8. Rewrite the query for question 7 to join the tables by using the WHERE clause.9. Rewrite the query for question 7 to list only employees who have not worked any hours for an

assigned project. This will provide the vice president for project management with a "needs to be motivated" list of employees. Use the FROM clause to join the tables.

10. Management is expecting to start several new projects in the near future. A list of employees who are not currently assigned to a project is needed. This will provide management with a list of employees who are potentially available to be assigned to projects. The result table should list the LastName and FirstName column values (concatenated into one column) from the employee table. Sort the output by LastName and FirstName. Use the FROM clause to join the tables. List only the first five rows of the result table in your lab report, but also list the number of rows selected by your query.

11. Rewrite the query for question 7. Replace the project number as an output column with the ProjectTitle column value from the project table. Rename the ProjectTitle column Project. . List only the first five rows of the result table in your lab report, but also list the number of rows selected by your query. All other requirements remain the same.

12. The patient census manager needs a listing of patients by last name, first name, and assigned bed number and room number. Use the patient and bed tables. Name each column appropriately. Concatenate the patient last and first names into a single column with names separated by a comma and space. Sort the result table by room number and bed number. Use the FROM clause to join the tables. List only the first five rows of the result table in your lab report. How many patients are assigned to beds at this time?

13. Produce a listing of employees that are managed by the manager of department 3. The result table should include the manager's last name, department name, and employee's last name – name each column "Supervisor," "Department," and "Employee Supervised," respectively. You must determine which tables and columns are required to produce the result table.

14. Produce a query that will list all employee last names, employee gender, dependent names and dependent gender where the employee's have dependents of the opposite gender. Also list the dependent relationship. The columns needed in the result table are LastName, employee.Gender, dependent.Name, dependent.Gender, and RelationshipToEmployee. Use the employee and dependent tables. Use the FROM clause to join the tables. Use the column names and formats shown below. Sort the result table by LastName.

COLUMN "Employee" FORMAT A10;COLUMN "Emp Gender" FORMAT A10;COLUMN "Dependent" FORMAT A10;COLUMN "Dep Gender" FORMAT A10;COLUMN "Relationship" FORMAT A12;

Revised September 22, 2007 6 - 25

Page 26: Chapter06 Oracle

Chapter 6

15. Several physicians have requested that you write a query that displays the patient history for hospital patients. This will assist them in diagnosing medical problems. Your result table displays the PatientID and LastName columns from the patient table and the PhysicianComment column from the PatientNote table. Use the FROM clause to join the tables and use the default column headings based on COLUMN-FORMAT statements shown here. Submit just the output from the first four result table rows displayed. How many rows in the result table are produced by your query?

COLUMN PatientID FORMAT A9;COLUMN LastName FORMAT A15;COLUMN PhysicianComment FORMAT A45;

16. Rewrite the query for question 15 to only list the patient history for the patient with identification 100303. Use the WHERE clause to join the tables.

17. The chief of surgery requires a listing of services provided by service category. Your query uses the service and serviceCategory tables. Display four columns as follows: service.CategoryID, serviceCategory.Description, service.ServiceID, and service.Description. Use headings of “Category,” “Category Description,” “Service,” and “Service Description,” respectively. Sort the output by service.CategoryID, then by service.ServiceID. Use the FROM clause to join the tables. Submit just the output from the first five result table rows displayed. How many rows in the result table are produced by your query?

18. Rewrite the query for question 17 to restrict the output to service categories with identifiers of CAR and LAB. All other requirements remain the same.

19. The chief of hospital resource utilization needs a listing of patients assigned to beds. The result table needs to include the patient name (last and first names concatenated as a single column), bed number, and bed type identifier. Use the patient and bed tables in writing the query. Use meaningful column names and sort the result table rows by the bed number. Use the WHERE clause to join the tables. Submit just the output from the first five result table rows displayed. How many rows in the result table are produced by your query?

20. The chief of hospital resource utilization is happy with the listing produced for Question 19, but now requests that you replace the BedType column with the Description column from the bedClassification table. Your new query joins three tables. Use the FROM clause to join the tables. Submit just the output from the first five result table rows displayed.

21. The chief of hospital resource utilization is visiting you again, this time to ask you to add a fourth column for the result table produced for Question 7. Add the Description column from the room table. Display this column as 15 characters. Your new query joins four tables. Join the tables by using the FROM clause. Submit just the output from the first five result table rows displayed.

22. The chief of physicians requires a listing of patients receiving treatment. The result table must display the patient name (last and first concatenated from the patient table), Description column (service table), and employee name providing the treatment (last and first name concatenated from the employee table). Sort the result table by the patient last name then first name. Your query joins four tables. Join the tables by using the FROM clause. Format each column of the result table. Submit just the output from the first five result table rows displayed. How many rows in the result table are produced by your query?

23. Rewrite the query for question 22 above by specifying the entire JOIN operation in the WHERE clause instead of the FROM clause.

Revised September 22, 2007 6 - 26

Page 27: Chapter06 Oracle

Chapter 6

24. The chief of pharmacy requires a listing of patients receiving prescriptions. The result table must display the patient name (last and first concatenated from the patient table), medicine common name (CommonName from the medicine table), and employee who prescribed the medicine (last and first name concatenated from the employee table). Sort the result table by the patient last then first name. Your query joins four tables. Join the tables by using the FROM clause. Format each column of the result table. Submit just the output from the first five result table rows displayed. How many rows in the result table are produced by your query?

25. Rewrite the query for question 24 to display rows only for patients prescribed Demerol. Submit all result table rows in your report.

26. Rewrite the query for question 24 to only display rows for patients prescribed medicine by Dr. Toni Quattromani (EmployeeID = 66425). Submit all result table rows in your report.

27. Rewrite the query for question 24 to display rows for patients either who were prescribed Lanoxin or where the doctor writing the prescription was Dr. Toni Quattromani (EmployeeID = 66425). Submit all result table rows in your report.

28. Management needs a listing of beds that are classified as bed type E2 Emergency Room-Fixed. The result table should list the BedType and Description columns of the bedClassification table and the RoomNumber and BedNumber of the bed table. Sort the output by RoomNumber and BedNumber. Use a NATURAL JOIN syntax in writing the query.

29. Management needs a listing of services provided within the service category SUR. You decide to use a NATURAL JOIN to produce a result table that includes the CategoryID and Description columns of the serviceCategory table and the ServiceID and Description columns of the service table. The query you wrote is shown here. Why does the result table contain no rows?

SELECT CategoryID, ServiceID, DescriptionFROM Service s NATURAL JOIN ServiceCategory WHERE CategoryID = 'SUR';

no rows selected

Revised September 22, 2007 6 - 27