Outer Joins

Outer Joins

Suppose that we to see information about customer purchases at the View Ridge Gallery. To do this, we can use the SQL query:

/* *** SQL-Query-CH07-06 *** */ SELECT

C.LastName, C.FirstName, T.TransactionsID, T.SalesPrice

FROM

CUSTOMER AS C JOIN TRANS AS T

ON

C.CustomerID = T.CustomerID

ORDER BY

T.TransactionID;

This query produces the large result set shown in Figure 7-17.

This result is correct, but it shows the names of only 8 of the 10 customers in the CUSTOMER table. What happened to the other two customers? Look closely at the data in Figure 7-16 and you will see that the two customers that do not appear in the results (Susan Wu and Lynda Johnson) are customers who have never made a purchase at the gallery. Therefore, the primary key value of these two customers does not match any foreign key value in the TRANS table, and because they have no match, they do not appear in the result of this join statement.

Because knowing which customers have not made any purchase is important information for View Ridge Gallery management, we want to include these customers in the query results. We can cause all of the rows in CUSTOMER to appear using what is called an SQL outer join. The SQL outer join syntax is shown in the query:

/* *** SQL-Query-CH07-07 *** */ SELECT

C.LastName, C.FirstName, T.TransactionsID, T.SalesPrice

FROM

CUSTOMER AS C LEFT JOIN TRANS AS T

(continued)

Figure 7-17

Result of JOIN of CUSTOMER and TRANS

Chapter 7 SQL for Database Construction and Application Processing

ON

C.CustomerID = T.CustomerID

ORDER BY

T.TransactionID;

The result of this query is shown in Figure 7-18. Notice that the values of TransactionID and SalesPrice are NULL for all customers (Susan Wu and Lynda Johnson) who have not made purchases.

Outer joins can be either from the left or the right. If the outer join is from the left, an SQL left outer join, which uses the SQL LEFT JOIN syntax, then all of the rows on the table on the left (or first table in the join statement) will be included in the result. Therefore Figure 7-18, which shows the results of a LEFT JOIN on CUSTOMER and TRANS, shows every CUSTOMER.LastName and CUSTOMER.FirstName value (because CUSTOMER is the table on the left —the first table in the JOIN), but displays matching values for TRANS.TransactionID and TRANS.SalesPrice only if they exist. If there are no matching TRANS.TransactionID and TRANS.SalesPrice and uses, then NULL values are displayed. This occurs 2 times—for Susan Wu (row 1) and Lynda Johnson (row 2).

If the outer join is on the right, an SQL right outer join, which uses the SQL RIGHT JOIN syntax, then all rows on the table on the right (or second table in the join statement) will be included in the result. To illustrate the use of a right outer join, we will use a modification of the preceding query we used to associate customers with transactions. With the left outer join, the NULLs showed customers who had not purchased a work. With the right outer join, the

Figure 7-18

Result of LEFT OUTER JOIN of CUSTOMER and TRANS

Part 3 Database Implementation

NULL will show works that have not been purchased by customers (and are therefore still in inventory and available for sale):

/* *** SQL-Query-CH07-08 *** */ SELECT

C.LastName, C.FirstName, T.TransactionsID, T.SalesPrice

FROM

CUSTOMER AS C RIGHT JOIN TRANS AS T

ON

C.CustomerID = T.CustomerID

ORDER BY

T.TransactionID;

The result for this right join query is shown in Figure 7-19.

Figure 7-19

Result of RIGHT OUTER JOIN of CUSTOMER and TRANS

Chapter 7 SQL for Database Construction and Application Processing

Figure 7-19, which shows the results of a RIGHT JOIN on CUSTOMER and TRANS, shows every TRANS.TransactionID and TRANS.SalesPrice value (because TRANS is the table on the right —the second table in the JOIN), but displays matching values for CUSTOMER.LastName and CUSTOMER.FirstName only if they exist. If there are no matching values, then NULL val- ues are displayed. This occurs ten times—for TransactionIDs 126 (row 10), 155 (row 18), 181 (row 23), 226 (row 27), 228 (row 29), 229 (row 30), 251 (row 32), 252 (row 33), 253 (row 34), and 254 (row 35). Each of these rows show NULL values for CUSTOMER columns because no cus- tomer has purchased the WORK referenced by the TransactionID value, and therefore there is no matching row in CUSTOMER for these rows in TRANS. Note that the NULL values in the SalesPrice column are not a result of the RIGHT JOIN, but exist simply because the referenced WORK has not been sold—they could show up in the results of a query against TRANS regard- less of whether or not it was a RIGHT join.

Joins that are not outer joins are called inner joins. All of the joins we have presented up to this discussion of outer have been inner joins, though we did not use that term. Outer joins can be combined to any level, just as inner joins can. The following SQL statement will obtain

a list of every customer and the artists in which they have an interest:

/* *** SQL-Query-CH07-09 *** */ SELECT

C.LastName, C.FirstName, A.LastName AS ArtistName

FROM

CUSTOMER AS C LEFT JOIN CUSTOMER_ARTIST_INT AS CAI

ON

C.CustomerID = CAI.CustomerID LEFT JOIN

ARTIST AS A ON CAI.ArtistID = A.ArtistID

ORDER BY

C.LastName, C.FirstName;

The result for this query is in Figure 7-20. Note that if we leave either LEFT keyword out of the expression the rows with NULL values for ArtistName will not appear in Figure 7-20. A variant of this query using right joins can also be run (if you are running these queries in a DBMS, then try it out), but note that because there is at least one customer interested in each artist (as shown in the data in Figure 7-16) there will be no NULL values in the result. Of course, that is a significant result, showing that customers are interested in all the artists featured at the View Ridge Gallery.

It is easy to forget that inner joins will drop nonmatching rows. Some years ago, one of the authors had a very large organization as a consulting client.

The client had a budgetary-planning application that included a long sequence of complicated SQL statements. One of the joins in that sequence was an inner join that should have been an outer join. As a result, some 3,000 employees dropped out of the budgetary calculations. The mistake was discovered only months later when the actual salary expense exceeded the budget salary expense by a large margin. The mistake was an embarrassment all the way to the board of directors.

Using SQL Views

An SQL view is a virtual table that is constructed from other tables or views. A view has no data of its own, but obtains data from tables or other views. Views are constructed from SQL SELECT statements using the SQL CREATE VIEW statement, and view names are then used just as table names would be in the FROM clause of other SQL SELECT statements. The only limitation on the SQL statements that are used to create views is that they may not contain an ORDER BY

clause. 1 The sort order must be provided by the SELECT statement that processes the view.

1 This limitation appears in the SQL-92 standard, but how views are actually implemented varies by DBMS product. For example, Oracle Database allows views to include ORDER BY, whereas SQL Server will only allow

ORDER BY in very limited circumstances.

Part 3 Database Implementation

Figure 7-20

Result of Nested LEFT OUTER JOINS of CUSTOMER, CUSTOMER_ARTIST_INT, and ARTIST

Views are a standard and popular SQL construct. Microsoft Access, however, does not support them. Instead, in Microsoft Access you can

create a view-equivalent query, name it, and then save it. You can then process the query in the same ways that we process views in the following discussion.

SQL Server, Oracle Database, and MySQL all support views, and they are an important structure with many uses. Do not conclude from Microsoft Access’ lack of support that views are unimportant. Read on, and, if possible, use SQL Server, Oracle Database, or MySQL to process the statements in this section.

The following statement defines a view named CustomerNameView on the CUSTOMER table:

/* *** SQL-CREATE-VIEW-CH07-01 *** */ CREATE VIEW CustomerNameView AS

SELECT

LastName AS CustomerLastName, FirstName AS CustomerFirstName,

FROM

CUSTOMER;

Chapter 7 SQL for Database Construction and Application Processing

Note that the results from executing this statement will be only a system message stating the action completed. With GUI utilities such as SQL Server Management Studio, an appropriately named object will also be created.

The current versions of SQL Server, Oracle Database, and MySQL all process the CREATE VIEW statements as written here without difficulty. However, an

earlier version of SQL Server, SQL Server 2000, has a quirk: to create views, you have to remove the semicolon from the CREATE VIEW statement. We have no idea why SQL Server 2000 accepts a semicolon for all other SQL statements but will not accept one for SQL statements that create views. If by chance you are still using SQL Server 2000, be aware that you must remove the semicolon when writing CREATE VIEW statements.

Once the view is created, it can be used in the FROM clause of SELECT statements, just like a table. The following obtains a list of customer names in sorted order:

/* *** SQL-Query-View-CH07-01 *** */ SELECT

* FROM

CustomerNameView ORDER BY

CustomerLastName, CustomerFirstName;

The result for the sample data in Figure 7-16 is:

Note that the number of columns returned in the result depends on the number of columns in the view, not on the number of columns in the underlying table. In this example, the SELECT clause produces just two columns because CustomerNameView itself has just two columns.

Also notice that the columns LastName and FirstName in the CUSTOMER table have been renamed to CustomerLastName and CustomerFirstName in the view. Because of this, the ORDER BY phrase in the SELECT statement uses CustomerLastName and CustomerFirst- Name, not LastName and FirstName. Also, the DBMS uses the labels CustomerLastName and CustomerFirstName when producing results.

If you need to change an SQL view after you have created it, use the SQL ALTER VIEW statement . For example, if you wanted to reverse the order of

LastName and FirstName in the CustomerNameView, you would use the SQL statement:

/* *** EXAMPLE CODE – DO NOT RUN *** */ /* *** SQL-ALTER-VIEW-CH07-01 *** */ ALTER VIEW CustomerNameView AS SELECT

FirstName AS CustomerFirstName, LastName AS CustomerLastName,

FROM CUSTOMER;

Part 3 Database Implementation

• Hide columns or rows • Display results of computations • Hide complicated SQL syntax • Layer built-in functions • Provide level of isolation between

table data and users’ view of data

Figure 7-21

• Assign different processing permissions

to different views of the same table

Uses of SQL Views • Assign different triggers to different views

of the same table

Figure 7-21 lists the uses for SQL views. SQL views can hide columns or rows. They also can be used to display the results of computed columns, to hide complicated SQL syntax, and to layer the use of built-in functions to create results that are not possible with a single SQL statement. Additionally, SQL views can provide an alias for table names and thus hide the true table names from applications and users. SQL views also are used to assign different processing permissions and different triggers to different views of the same table. We will show examples for each of these.