1. Trang chủ
  2. » Công Nghệ Thông Tin

SQL VISUAL QUICKSTART GUIDE- P28 pps

10 239 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 178,14 KB

Nội dung

For every biography, Listing 7.35 lists the other biographies that outsold it. Note that the WHERE search condition requires type = ‘biography’ for both tables t1 and t2 because the join condition considers the column type to be two separate columns. See Figure 7.35 for the result. ✔ Tip ■ Using WHERE syntax, Listing 7.35 is equiv- alent to: SELECT t1.title_id, t1.sales, t2.title_id AS “Better seller”, t2.sales AS “Higher sales” FROM titles t1, titles t2 WHERE t1.sales < t2.sales AND t1.type = ‘biography’ AND t2.type = ‘biography’ ORDER BY t1.title_id ASC, t2.sales ASC; 250 Chapter 7 Creating a Self-Join Listing 7.35 For every biography, list the title ID and sales of the other biographies that outsold it. See Figure 7.35 for the result. SELECT t1.title_id, t1.sales, t2.title_id AS "Better seller", t2.sales AS "Higher sales" FROM titles t1 INNER JOIN titles t2 ON t1.sales < t2.sales WHERE t1.type = 'biography' AND t2.type = 'biography' ORDER BY t1.title_id ASC, t2.sales ASC; Listing title_id sales Better seller Higher sales T06 11320 T12 100001 T06 11320 T07 1500200 T12 100001 T07 1500200 Figure 7.35 Result of Listing 7.35. Listing 7.36 is a self-join to find all pairs of authors within New York state. See Figure 7.36 for the result. ✔ Tip ■ Using WHERE syntax, Listing 7.36 is equivalent to: SELECT a1.au_fname, a1.au_lname, a2.au_fname, a2.au_lname FROM authors a1, authors a2 WHERE a1.state = a2.state AND a1.state = ‘NY’ ORDER BY a1.au_id ASC, a2.au_id ASC; 251 Joins Creating a Self-Join Listing 7.36 List all pairs of authors who live in New York state. See Figure 7.36 for the result. SELECT a1.au_fname, a1.au_lname, a2.au_fname, a2.au_lname FROM authors a1 INNER JOIN authors a2 ON a1.state = a2.state WHERE a1.state = 'NY' ORDER BY a1.au_id ASC, a2.au_id ASC; Listing au_fname au_lname au_fname au_lname Sarah Buchman Sarah Buchman Sarah Buchman Christian Kells Christian Kells Sarah Buchman Christian Kells Christian Kells Figure 7.36 Result of Listing 7.36. Figure 7.37 still isn’t quite what I want, because the two result rows are redundant. The first row states that Sarah Buchman lives in the same state as Christian Kells, and the second row gives the same informa- tion. To eliminate this redundancy, I’ll change the second join condition’s comparison oper- ator from not-equal to less-than (Listing 7.38 and Figure 7.38). ✔ Tip ■ Using WHERE syntax, Listing 7.38 is equiv- alent to: SELECT a1.au_fname, a1.au_lname, a2.au_fname, a2.au_lname FROM authors a1, authors a2 WHERE a1.state = a2.state AND a1.au_id < a2.au_id AND a1.state = ‘NY’ ORDER BY a1.au_id ASC, a2.au_id ASC; The first and fourth rows of Figure 7.36 are unnecessary because they indicate that Sarah Buchman lives in the same state as Sarah Buchman, and likewise for Christian Kells. Adding a join condition retains only those rows in which the two authors differ (Listing 7.37 and Figure 7.37). ✔ Tip ■ Using WHERE syntax, Listing 7.37 is equiv- alent to: SELECT a1.au_fname, a1.au_lname, a2.au_fname, a2.au_lname FROM authors a1, authors a2 WHERE a1.state = a2.state AND a1.au_id <> a2.au_id AND a1.state = ‘NY’ ORDER BY a1.au_id ASC, a2.au_id ASC; 252 Chapter 7 Creating a Self-Join Listing 7.37 List all different pairs of authors who live in New York state. See Figure 7.37 for the result. SELECT a1.au_fname, a1.au_lname, a2.au_fname, a2.au_lname FROM authors a1 INNER JOIN authors a2 ON a1.state = a2.state AND a1.au_id <> a2.au_id WHERE a1.state = 'NY' ORDER BY a1.au_id ASC, a2.au_id ASC; Listing au_fname au_lname au_fname au_lname Sarah Buchman Christian Kells Christian Kells Sarah Buchman Figure 7.37 Result of Listing 7.37. Listing 7.38 List all different pairs of authors who live in New York state, with no redundancies. See Figure 7.38 for the result. SELECT a1.au_fname, a1.au_lname, a2.au_fname, a2.au_lname FROM authors a1 INNER JOIN authors a2 ON a1.state = a2.state AND a1.au_id < a2.au_id WHERE a1.state = 'NY' ORDER BY a1.au_id ASC, a2.au_id ASC; Listing au_fname au_lname au_fname au_lname Sarah Buchman Christian Kells Figure 7.38 Result of Listing 7.38. To this point, I’ve used a single SELECT state- ment to retrieve data from one or more tables. This chapter describes nested queries, which let you retrieve or modify data based on another query’s result. A subquery, or subselect, is a SELECT state- ment embedded in another SQL statement. You can nest a subquery in: ◆ The SELECT , FROM , WHERE , or HAVING clause of a SELECT statement ◆ Another subquery ◆ An INSERT , UPDATE , or DELETE statement In general, you can use a subquery anywhere an expression is allowed, but your DBMS might restrict where they can appear. This chapter covers subqueries nested in a SELECT statement or another subquery; Chapter 10 covers subqueries embedded in INSERT , UPDATE , and DELETE statements. 253 Subqueries 8 Subqueries Understanding Subqueries This section defines some terms and intro- duces subqueries by giving an example of a SELECT statement that contains a simple sub- query. Subsequent sections explain the types of subqueries and their syntax and semantics. Suppose that you want to list the names of the publishers of biographies. The naive approach is to write two queries: one query to retrieve the IDs of all the biography pub- lishers (Listing 8.1 and Figure 8.1) and a second query that uses the first query’s result to list the publisher names (Listing 8.2 and Figure 8.2). A better way is to use an inner join (Listing 8.3 and Figure 8.3); see “Creating an Inner Join with INNER JOIN ” in Chapter 7. Another alternative is to use a subquery (Listing 8.4 and Figure 8.4). The subquery in Listing 8.4 is shown in red. A subquery also is called an inner query, and the state- ment containing a subquery is called an outer query. In other words, an enclosed sub- query is an inner query of an outer query. Remember that a subquery can be nested in another subquery, so inner and outer are relative terms in statements with multiple nested subqueries. 254 Chapter 8 Understanding Subqueries Listing 8.1 List the biography publishers. See Figure 8.1 for the result. SELECT pub_id FROM titles WHERE type = 'biography'; Listing pub_id P01 P03 P01 P01 Figure 8.1 Result of Listing 8.1. You can add DISTINCT to the SELECT clause of Listing 8.1 to list the publishers only once; see “Eliminating Duplicate Rows with DISTINCT ” in Chapter 4. Listing 8.2 This query uses the result of Listing 8.1 to list the names of the biography publishers. See Figure 8.2 for the result. SELECT pub_name FROM publishers WHERE pub_id IN ('P01', 'P03'); Listing pub_name Abatis Publishers Schadenfreude Press Figure 8.2 Result of Listing 8.2. I’ll explain how a DBMS executes subqueries in “Simple and Correlated Subqueries” later in this chapter, but for now, all that you need to know is that in Listing 8.4, the DBMS processes the inner query (in red) first and then uses its interim result to run the outer query (in black) and get the final result. The IN keyword that introduces the subquery tests for list membership and works like IN in “List Filtering with IN ” in Chapter 4. Note that the inner query in Listing 8.4 is the same query as Listing 8.1, and the outer query is the same query as Listing 8.2. ✔ Tips ■ Sometimes you’ll see the term subquery used to refer to an entire SQL statement that contains one or more subqueries. To prevent confusion, I don’t use that terminology in this book. ■ MySQL 4.1 and later support subqueries, but earlier versions don’t. You can’t run the examples in this chapter if you’re using MySQL 4.0 or earlier, but you have a few choices, in order of preference: ◆ Upgrade to the latest version of MySQL ( www.mysql.com ). ◆ Recast the subquery as a join (see “Subqueries vs. Joins” later in this chapter). ◆ Create a temporary table to hold the result of a subquery (see “Creating a Temporary Table with CREATE TEMPORARY TABLE ” in Chapter 11 and the temporary- table example in the DBMS Tip in “Creating Outer Joins with OUTER JOIN ” in Chapter 7, Listing 7.32). ◆ Simulate the subquery in a procedural host language such as PHP or Java (not covered in this book). 255 Subqueries Understanding Subqueries Listing 8.3 List the names of the biography publishers by using an inner join. See Figure 8.3 for the result. SELECT DISTINCT pub_name FROM publishers p INNER JOIN titles t ON p.pub_id = t.pub_id WHERE t.type = 'biography'; Listing pub_name Abatis Publishers Schadenfreude Press Figure 8.3 Result of Listing 8.3. Listing 8.4 List the names of the biography publishers by using a subquery. See Figure 8.4 for the result. SELECT pub_name FROM publishers WHERE pub_id IN (SELECT pub_id FROM titles WHERE type = 'biography'); Listing pub_name Abatis Publishers Schadenfreude Press Figure 8.4 Result of Listing 8.4. Subquery Syntax The syntax of a subquery is the same as that of a normal SELECT statement (see Chapters 4 through 7) except for the follow- ing differences: ◆ You can nest a subquery in a SELECT , FROM , WHERE , or HAVING clause or in another subquery. ◆ Always enclose a subquery in parentheses. ◆ Don’t terminate a subquery with a semi- colon. (You still must terminate the statement that contains the subquery with a semicolon.) ◆ Don’t put an ORDER BY clause in a subquery. (A subquery returns an intermediate result that you never see, so sorting a subquery makes no sense.) ◆ Asubquery is a single SELECT statement. (You can’t use, say, a UNION of multiple SELECT statements as a subquery.) ◆ A subquery can use columns in the tables listed in its own FROM clause or in the outer query’s FROM clause. ◆ If a table appears in an inner query but not in the outer query, you can’t include that table’s columns in the final result (that is, in the outer query’s SELECT clause). ◆ Depending on the context in which it’s used, a subquery might be required to return a limited number of rows or columns. The SQL standard categorizes a subquery by the number of rows and columns it returns (Table 8.1). In all cases, the subquery also can return an empty table (zero rows). In practice, a subquery usually appears in a WHERE clause that takes one of these forms: ◆ WHERE test_expr op (subquery) ◆ WHERE test_expr [NOT] IN (subquery) ◆ WHERE test_expr op ALL (subquery) ◆ WHERE test_expr op ANY (subquery) ◆ WHERE [NOT] EXISTS (subquery) test_expr is a literal value, a column name, an expression, or a scalar subquery; op is a comparison operator ( = , <> , < , <= , > , or >= ); and subquery is a simple or correlated sub- query. I’ll cover each of these forms later in this chapter. You can use these subquery forms in a HAVING clause, too. ✔ Tip ■ The SQL standard doesn’t specify a maximum number of subquery nesting levels, so your DBMS will set its own upper limit. This built-in limit typically exceeds the limit of human comprehension. Microsoft SQL Server, for example, allows 32 levels of nesting. 256 Chapter 8 Subquery Syntax Table 8.1 Size of Subquery Results Subquery Rows Columns Scalar subquery 1 1 Row subquery 1 ≥1 Table subquery ≥1 ≥1 Subqueries vs. Joins In “Understanding Subqueries” earlier in this chapter, Listings 8.3 and 8.4 showed two equivalent queries: one used a join, and the other used a subquery. Many subqueries can be formulated alternatively as joins. In fact, a subquery is a way to relate one table to another without actually doing a join. Because subqueries can be hard to use and debug, you might prefer to use joins, but you can pose some questions only as subqueries. In cases where you can use subqueries and joins interchangeably, you should test queries on your DBMS to see whether a perform- ance difference exists between a statement that uses a subquery and a semantically equivalent version that uses a join. For example, the query SELECT MAX(table1.col1) FROM table1 WHERE table1.col1 IN (SELECT table2.col1 FROM table2); usually will run faster than SELECT MAX(table1.col1) FROM table1 INNER JOIN table2 ON table1.col1 = table2.col1; For more information, see “Comparing Equivalent Queries” later in this chapter. 257 Subqueries Subqueries vs. Joins The following syntax diagrams show some equivalent statements that use subqueries and joins. These two statements are equiva- lent ( IN subquery): SELECT * FROM table1 WHERE id IN (SELECT id FROM table2); and (inner join): SELECT DISTINCT table1.* FROM table1 INNER JOIN table2 ON table1.id = table2.id; See Listings 8.5a and 8.5b and Figure 8.5 for an example. 258 Chapter 8 Subqueries vs. Joins Listing 8.5a This statement uses a subquery to list the authors who live in the same city in which a publisher is located. See Figure 8.5 for the result. SELECT au_id, city FROM authors WHERE city IN (SELECT city FROM publishers); Listing Listing 8.5b This statement is equivalent to Listing 8.5a but uses an inner join instead of a subquery. See Figure 8.5 for the result. SELECT DISTINCT a.au_id, a.city FROM authors a INNER JOIN publishers p ON a.city = p.city; Listing au_id city A03 San Francisco A04 San Francisco A05 New York Figure 8.5 Result of Listings 8.5a and 8.5b. These three statements are equivalent ( NOT IN subquery): SELECT * FROM table1 WHERE id NOT IN (SELECT id FROM table2); and ( NOT EXISTS subquery): SELECT * FROM table1 WHERE NOT EXISTS (SELECT * FROM table2 WHERE table1.id = table2.id); and (left outer join): SELECT table1.* FROM table1 LEFT OUTER JOIN table2 ON table1.id = table2.id WHERE table2.id IS NULL; See Listings 8.6a, 8.6b, and 8.6c and Figure 8.6 for an example. IN and EXISTS subqueries are covered later in this chapter. 259 Subqueries Subqueries vs. Joins Listing 8.6a This statement uses an IN subquery to list the authors who haven’t written (or cowritten) a book. See Figure 8.6 for the result. SELECT au_id, au_fname, au_lname FROM authors WHERE au_id NOT IN (SELECT au_id FROM title_authors); Listing Listing 8.6b This statement is equivalent to Listing 8.6a but uses an EXISTS subquery instead of an IN subquery. See Figure 8.6 for the result. SELECT au_id, au_fname, au_lname FROM authors a WHERE NOT EXISTS (SELECT * FROM title_authors ta WHERE a.au_id = ta.au_id); Listing Listing 8.6c This statement is equivalent to Listings 8.6a and 8.6b but uses a left outer join instead of a subquery. See Figure 8.6 for the result. SELECT a.au_id, a.au_fname, a.au_lname FROM authors a LEFT OUTER JOIN title_authors ta ON a.au_id = ta.au_id WHERE ta.au_id IS NULL; Listing au_id au_fname au_lname A07 Paddy O'Furniture Figure 8.6 Result of Listings 8.6a, 8.6b, and 8.6c. . in this chapter if you’re using MySQL 4.0 or earlier, but you have a few choices, in order of preference: ◆ Upgrade to the latest version of MySQL ( www.mysql.com ). ◆ Recast the subquery. subquery used to refer to an entire SQL statement that contains one or more subqueries. To prevent confusion, I don’t use that terminology in this book. ■ MySQL 4.1 and later support subqueries,. on another query’s result. A subquery, or subselect, is a SELECT state- ment embedded in another SQL statement. You can nest a subquery in: ◆ The SELECT , FROM , WHERE , or HAVING clause of a

Ngày đăng: 05/07/2014, 05:20

TỪ KHÓA LIÊN QUAN