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

SQL VISUAL QUICKSTART GUIDE- P31 ppt

10 183 0
Tài liệu đã được kiểm tra trùng lặp

Đ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 187,49 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Here’s the join version of Listing 8.33: SELECT DISTINCT pub_name FROM publishers p INNER JOIN titles t ON p.pub_id = t.pub_id AND type = ‘biography’; Listing 8.33 List the names of the

Trang 1

Listing 8.31 uses a correlated subquery to

imitate a GROUP BYclause and list all books

that have a price greater than the average

for books of its type For each possible value

oft1, the DBMS evaluates the subquery and

includes the row in the result if the price

value in that row exceeds the calculated

average It’s unnecessary to group by type

explicitly, because the rows for which the

average price is calculated are restricted by

the subquery’s WHEREclause See Figure 8.31

for the result

Listing 8.32 uses the same structure as

Listing 8.31 to list all the books whose sales

are less than the best-selling books of their

types See Figure 8.32 for the result.

✔ Tips

■ If a subquery returns more than one row,

you can use ALLorANYto modify the

comparison operator, or you can

intro-duce the subquery with IN (ALL,ANY, and

INare covered later in this chapter.)

MySQL 4.0 and earlier don’t

support subqueries; see the DBMS Tip in “Understanding Subqueries”

earlier in this chapter

Listing 8.31 List all books that have a price greater

than the average for books of its type See Figure 8.31 for the result.

SELECT type, title_id, price FROM titles t1

WHERE price >

(SELECT AVG(t2.price) FROM titles t2 WHERE t1.type = t2.type) ORDER BY type ASC, title_id ASC;

Listing

type title_id price - -biography T06 19.95 biography T07 23.95 children T09 13.95 history T13 29.99 psychology T04 12.99

Figure 8.31 Result of Listing 8.31.

Listing 8.32 List all the books whose sales are

less than the best-selling books of their types See Figure 8.32 for the result.

SELECT type, title_id, sales FROM titles t1

WHERE sales <

(SELECT MAX(sales) FROM titles t2 WHERE t1.type = t2.type AND sales IS NOT NULL) ORDER BY type ASC, title_id ASC;

Listing

type title_id sales -biography T06 11320 biography T12 100001 children T08 4095 history T01 566 history T02 9566 psychology T04 13001 psychology T11 94123

Trang 2

Testing Set Membership

with IN

“List Filtering with IN” in Chapter 4 describes how to use the INkeyword in a WHEREclause

to compare a literal, column value, or more-complex expression to a list of values You

also can use a subquery to generate the list

The important characteristics of a subquery set membership test are:

◆ INworks the same way with the values

in a subquery result as it does with a

parenthesized list of values (see “List

Filtering with IN” in Chapter 4)

◆ The subquery can be simple or correlated (see “Simple and Correlated Subqueries” earlier in this chapter)

◆ The subquery’s SELECT-clause list

can include only one expression or

column name

◆ The compared values must have the

same data type or must be implicitly

convertible to the same type (see

“Converting Data Types with CAST()”

in Chapter 5)

◆ String comparisons are case insensitive

or case sensitive, depending on your

DBMS; see the DBMS Tip in “Filtering

Rows with WHERE” in Chapter 4

◆ The subquery must return exactly one

column and zero or more rows A

sub-query that returns more than one column will cause an error

◆ You can use NOT INto reverse the effect

of the INtest If you specify NOT IN, the

DBMS takes the action specified by the

SQL statement if there is no matching

value in the subquery’s result

Trang 3

To test set membership:

◆ In the WHEREclause of a SELECT

state-ment, type:

WHERE test_expr [NOT] IN (subquery)

test_expr is a literal value, a column

name, an expression, or a subquery that

returns a single value; and subquery is a

subquery that returns one column and

zero or more rows

If the value of test_expr equals any value

returned by subquery, the INcondition

evaluates to true The INcondition is false

if the subquery result is empty, if no row

in the subquery result matches test_expr,

or if all the values in the subquery result

are null Specify NOTto negate the

condi-tion’s result

The same syntax applies to a HAVINGclause:

HAVING test_expr [NOT] IN (subquery)

Listing 8.33 lists the names of the publishers

that have published biographies The DBMS

evaluates this statement in two steps First,

the inner query returns the IDs of the

pub-lishers that have published biographies (P01

and P03) Second, the DBMS substitutes these

values into the outer query, which finds

the names that go with the IDs in the table

publishers See Figure 8.33 for the result.

Here’s the join version of Listing 8.33:

SELECT DISTINCT pub_name

FROM publishers p

INNER JOIN titles t

ON p.pub_id = t.pub_id

AND type = ‘biography’;

Listing 8.33 List the names of the publishers that have

published biographies See Figure 8.33 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.33 Result of Listing 8.33.

Listing 8.34 List the names of the publishers that

haven’t published biographies See Figure 8.34 for the result.

SELECT pub_name FROM publishers WHERE pub_id NOT IN

(SELECT pub_id FROM titles WHERE type = 'biography');

Listing

pub_name -Core Dump Books Tenterhooks Press

Figure 8.34 Result of Listing 8.34.

Trang 4

Listing 8.34 is the same as Listing 8.33,

except that it uses NOT INto list the names

of the publishers that haven’t published

biographies See Figure 8.34 for the result.

This statement can’t be converted to a join

The analogous not-equal join has a different meaning: It lists the names of publishers

that have published some book that isn’t

a biography

Listing 8.35 is equivalent to Listing 7.31 in

Chapter 7, except that it uses a subquery instead of an outer join to list the authors who haven’t written (or cowritten) a book

See Figure 8.35 for the result.

Listing 8.36 lists the names of the authors

who have published a book with publisher P03 (Schadenfreude Press) The join to the table authorsis necessary to include the authors’ names (not just their IDs) in the

result See Figure 8.36 for the result.

Listing 8.35 List the authors who haven’t written (or

cowritten) a book See Figure 8.35 for the result.

SELECT au_id, au_fname, au_lname

FROM authors

WHERE au_id NOT IN

(SELECT au_id

FROM title_authors);

Listing

au_id au_fname au_lname

- -

-A07 Paddy O'Furniture

Figure 8.35 Result of Listing 8.35.

Listing 8.36 List the names of the authors who have

published a book with publisher P03 See Figure 8.36

for the result.

SELECT DISTINCT a.au_id, au_fname, au_lname

FROM title_authors ta

INNER JOIN authors a

ON ta.au_id = a.au_id

WHERE title_id IN

(SELECT title_id

FROM titles

WHERE pub_id = 'P03');

Listing

au_id au_fname au_lname

- -

-A01 Sarah Buchman

A02 Wendy Heydemark

A04 Klee Hull

Figure 8.36 Result of Listing 8.36.

Trang 5

A subquery can itself include one or more

subqueries Listing 8.37 lists the names of

authors who have participated in writing at

least one biography The innermost query

returns the title IDs T06, T07, T10, and T12

The DBMS evaluates the subquery at the

next higher level by using these title IDs and

returns the author IDs Finally, the

outer-most query uses the author IDs to find the

names of the authors See Figure 8.37 for

the result

Excessive subquery nesting makes a

state-ment hard to read; often, it’s easier to restate

the query as a join Here’s the join version of

Listing 8.37:

SELECT DISTINCT a.au_id, au_fname,

au_lname

FROM authors a

INNER JOIN title_authors ta

ON a.au_id = ta.au_id

INNER JOIN titles t

ON t.title_id = ta.title_id

WHERE type = ‘biography’;

Listing 8.38 lists the names of all

non-lead authors (au_order > 1) who live in

California and who receive less than 50

percent of the royalties for a book See

Figure 8.38 for the result.

Here’s the join version of Listing 8.38:

SELECT DISTINCT a.au_id, au_fname,

au_lname

FROM authors a

INNER JOIN title_authors ta

ON a.au_id = ta.au_id

WHERE state = ‘CA’

AND royalty_share < 0.5

AND au_order > 1;

Listing 8.37 List the names of authors who have

participated in writing at least one biography See Figure 8.37 for the result.

SELECT au_id, au_fname, au_lname FROM authors

WHERE au_id IN

(SELECT au_id FROM title_authors WHERE title_id IN

(SELECT title_id FROM titles WHERE type = 'biography'));

Listing

au_id au_fname au_lname - - -A02 Wendy Heydemark A04 Klee Hull

Figure 8.37 Result of Listing 8.37.

Listing 8.38 List the names of all ancillary authors

who live in California and who receive less than 50 percent of the royalties for a book See Figure 8.38 for the result.

SELECT au_id, au_fname, au_lname FROM authors

WHERE state = 'CA' AND au_id IN

(SELECT au_id FROM title_authors WHERE royalty_share < 0.5 AND au_order > 1);

Listing

au_id au_fname au_lname - -A03 Hallie Hull A04 Klee Hull

Trang 6

Listing 8.39 lists the names of authors

who are coauthors of a book To determine whether an author is a coauthor or the sole author of a book, examine his or her royalty share for the book If the royalty share is less than 100 percent (1.0), the author is a coauthor; otherwise, he or she is the sole

author See Figure 8.39 for the result.

Listing 8.40 uses a correlated subquery

to list the names of authors who are sole authors of a book—that is, authors who earn

100 percent (1.0) of the royalty on a book

See Figure 8.40 for the result The DBMS

considers each row in the outer-query table authorsto be a candidate for inclusion in the result When the DBMS examines the first candidate row in authors, it sets the correlation variable a.au_idequal to A01 (Sarah Buchman), which it substitutes into the inner query:

SELECT royalty_share FROM title_authors ta WHERE ta.au_id = ‘A01’;

The inner query returns 1.0, so the outer query evaluates to:

SELECT a.au_id, au_fname, au_lname FROM authors a

WHERE 1.0 IN (1.0)

TheWHEREcondition is true, so author A01 is included in the result The DBMS repeats this procedure for every author; see “Simple and Correlated Subqueries” earlier in this chapter

Listing 8.39 List the names of authors who are

coauthors of a book See Figure 8.39 for the result.

SELECT au_id, au_fname, au_lname

FROM authors a

WHERE au_id IN

(SELECT au_id

FROM title_authors

WHERE royalty_share < 1.0);

Listing

au_id au_fname au_lname

- -

-A02 Wendy Heydemark

A03 Hallie Hull

A04 Klee Hull

A06 Kellsey

Figure 8.39 Result of Listing 8.39.

Listing 8.40 List the names of authors who are sole

authors of a book See Figure 8.40 for the result.

SELECT a.au_id, au_fname, au_lname

FROM authors a

WHERE 1.0 IN

(SELECT royalty_share

FROM title_authors ta

WHERE ta.au_id = a.au_id);

Listing

au_id au_fname au_lname

-

-A01 Sarah Buchman

A02 Wendy Heydemark

A04 Klee Hull

A05 Christian Kells

A06 Kellsey

Figure 8.40 Result of Listing 8.40.

Trang 7

Listing 8.41 lists the names of authors who

are both coauthors and sole authors The

inner query returns the author IDs of sole

authors, and the outer query compares these

IDs with the IDs of the coauthors See

Figure 8.41 for the result.

You can rewrite Listing 8.41 as a join or as

an intersection Here’s the join version of

Listing 8.41:

SELECT DISTINCT a.au_id, au_fname,

au_lname

FROM authors a

INNER JOIN title_authors ta1

ON a.au_id = ta1.au_id

INNER JOIN title_authors ta2

ON a.au_id = ta2.au_id

WHERE ta1.royalty_share < 1.0

AND ta2.royalty_share = 1.0;

Here’s the intersection version of Listing 8.41

(see “Finding Common Rows with

INTERSECT” in Chapter 9):

SELECT DISTINCT a.au_id, au_fname,

au_lname

FROM authors a

INNER JOIN title_authors ta

ON a.au_id = ta.au_id

WHERE ta.royalty_share < 1.0

INTERSECT

SELECT DISTINCT a.au_id, au_fname,

au_lname

FROM authors a

INNER JOIN title_authors ta

ON a.au_id = ta.au_id

WHERE ta.royalty_share = 1.0;

Listing 8.41 List the names of authors who are both

coauthors and sole authors See Figure 8.41 for the result.

SELECT DISTINCT a.au_id, au_fname, au_lname FROM authors a

INNER JOIN title_authors ta

ON a.au_id = ta.au_id WHERE ta.royalty_share < 1.0

AND a.au_id IN

(SELECT a.au_id FROM authors a INNER JOIN title_authors ta

ON a.au_id = ta.au_id AND ta.royalty_share = 1.0 );

Listing

au_id au_fname au_lname - - -A02 Wendy Heydemark A04 Klee Hull A06 Kellsey

Figure 8.41 Result of Listing 8.41.

Listing 8.42 List the types of books common to more

than one publisher See Figure 8.42 for the result.

SELECT DISTINCT t1.type FROM titles t1 WHERE t1.type IN

(SELECT t2.type FROM titles t2 WHERE t1.pub_id <> t2.pub_id );

Listing

type -biography history

Trang 8

Listing 8.42 uses a correlated subquery to

list the types of books published by more than

one publisher See Figure 8.42 for

the result

Here’s the self-join version of Listing 8.42:

SELECT DISTINCT t1.type

FROM titles t1

INNER JOIN titles t2

ON t1.type = t2.type

AND t1.pub_id <> t2.pub_id;

✔ Tips

■ INis equivalent to = ANY; see “Comparing

Some Subquery Values with ANY” later in

this chapter

■ NOT INis equivalent to <> ALL(not<>

ANY); see “Comparing All Subquery

Values with ALL” later in this chapter

■ To run Listing 8.41 in

Microsoft Access, type:

SELECT DISTINCT a.au_id, au_fname,

au_lname

FROM (authors AS a

INNER JOIN title_authors AS ta1

ON a.au_id = ta1.au_id)

INNER JOIN title_authors AS ta2

ON a.au_id = ta2.au_id

WHERE ta1.royalty_share < 1.0

AND ta2.royalty_share = 1.0;

MySQL 4.0 and earlier don’t support

subqueries; see the DBMS Tip in

“Understanding Subqueries” earlier in

this chapter

In older PostgreSQL versions,

con-vert the floating-point numbers in

Listings 8.38 through 8.41 to DECIMAL;

see “Converting Data Types with CAST()”

in Chapter 5 To run Listings 8.38 through 8.41, change the floating-point literals

to (Listing 8.38):

CAST(0.5 AS DECIMAL) and (Listing 8.39):

CAST(1.0 AS DECIMAL) and (Listing 8.40):

CAST(1.0 AS DECIMAL) and (Listing 8.41):

CAST(1.0 AS DECIMAL)(in two places) Some DBMSs let you test multiple values simultaneously by using this syntax:

SELECT columns FROM table1 WHERE (col1, col2, , colN) IN (SELECT colA, colB, , colN FROM table2);

The test expression (left of IN) is a

paren-thesized list of table1 columns The

subquery returns the same number of columns as there are in the list The DBMS compares the values in correspon-ding columns The following query, for

example, works in Oracle, DB2, MySQL, and PostgreSQL:

SELECT au_id, city, state FROM authors

WHERE (city, state) IN (SELECT city, state FROM publishers);

The result lists the authors who live in the same city and state as some publisher:

au_id city state

————— ————————————— —————

A03 San Francisco CA A04 San Francisco CA A05 New York NY

Trang 9

Comparing All Subquery

Values with ALL

You can use the ALLkeyword to determine

whether a value is less than or greater than

all the values in a subquery result.

The important characteristics of subquery

comparisons that use ALLare:

◆ ALLmodifies a comparison operator in a

subquery comparison test and follows =,

<>,<,<=,>, or >=; see “Comparing a

Subquery Value by Using a Comparison

Operator” earlier in this chapter

◆ The combination of a comparison

opera-tor and ALLtells the DBMS how to apply

the comparison test to the values returned

by a subquery < ALL, for example, means

less than every value in the subquery

result, and > ALLmeans greater than

every value in the subquery result

◆ When ALLis used with <,<=,>, or >=, the

comparison is equivalent to evaluating

the subquery result’s minimum or

maxi-mum value < ALLmeans less than every

subquery value—in other words, less

than the minimum value > ALLmeans

greater than every subquery value—that

is, greater than the maximum value

Table 8.2 shows equivalent ALL

expres-sions and column functions Listing 8.45

later in this section shows how to

repli-cate a > ALLquery by using MAX()

◆ Semantic equivalence doesn’t mean that

two queries will run at the same speed.

For example, the query SELECT * FROM table1 WHERE col1 > ANY (SELECT MAX(col1) FROM table2); usually is faster than

SELECT * FROM table1 WHERE col1 > ALL (SELECT col1 FROM table2); For more information, see “Comparing Equivalent Queries” later in this chapter

◆ The comparison = ALLis valid but isn’t often used = ALLalways will be false unless all the values returned by the subquery are identical (and equal to the test value)

◆ The subquery can be simple or correlated (see “Simple and Correlated Subqueries” earlier in this chapter)

◆ The subquery’s SELECT-clause list can include only one expression or column name

◆ The compared values must have the same data type or must be implicitly convertible to the same type (see

“Converting Data Types with CAST()”

in Chapter 5)

◆ String comparisons are case insensitive

or case sensitive, depending on your DBMS; see the DBMS Tip in “Filtering Rows with WHERE” in Chapter 4

◆ The subquery must return exactly one column and zero or more rows A sub-query that returns more than one column will cause an error

◆ If the subquery returns no rows, the ALL condition is true (You might find this result to be counterintuitive.)

Table 8.2

ALL Equivalencies

A L L E x p r e s s i o n C o l u m n F u n c t i o n

< ALL(subquery) < MIN(subquery values)

> ALL(subquery) > MAX(subquery values)

Trang 10

To compare all subquery values:

◆ In the WHEREclause of a SELECT state-ment, type:

WHERE test_expr op ALL (subquery)

test_expr is a literal value, a column

name, an expression, or a subquery

that returns a single value; op is a

com-parison operator (=,<>,<,<=,>, or >=);

and subquery is a subquery that returns

one column and zero or more rows

TheALLcondition evaluates to true if

all values in subquery satisfy the ALL con-dition or if the subquery result is empty (has zero rows) The ALLcondition is false

if any (at least one) value in subquery

doesn’t satisfy the ALLcondition or if any value is null

The same syntax applies to a HAVINGclause:

HAVING test_expr op ALL (subquery)

Listing 8.43 lists the authors who live in a

city in which no publisher is located The inner query finds all the cities in which publishers are located, and the outer query compares each author’s city to all the

pub-lishers’ cities See Figure 8.43 for the result.

You can use NOT INto replicate Listing 8.43:

SELECT au_id, au_lname, au_fname, city FROM authors

WHERE city NOT IN (SELECT city FROM publishers);

Listing 8.44 lists the nonbiographies that

are priced less than all the biographies The inner query finds all the biography prices

The outer query inspects the lowest price in the list and determines whether each

non-biography is cheaper See Figure 8.44 for the

result The price IS NOT NULLcondition is required because the price of biography T10

is null Without this condition, the entire

Listing 8.43 List the authors who live in a city in which

no publisher is located See Figure 8.43 for the result.

SELECT au_id, au_lname, au_fname, city

FROM authors

WHERE city <> ALL

(SELECT city

FROM publishers);

Listing

au_id au_lname au_fname city

- -

-A01 Buchman Sarah Bronx

A02 Heydemark Wendy Boulder

A06 Kellsey Palo Alto

A07 O'Furniture Paddy Sarasota

Figure 8.43 Result of Listing 8.43.

Listing 8.44 List the nonbiographies that are cheaper

than all the biographies See Figure 8.44 for the result.

SELECT title_id, title_name

FROM titles

WHERE type <> 'biography'

AND price < ALL

(SELECT price

FROM titles

WHERE type = 'biography'

AND price IS NOT NULL );

Listing

title_id title_name

-

-T05 Exchange of Platitudes

T08 Just Wait Until After School

T11 Perhaps It's a Glandular Problem

Figure 8.44 Result of Listing 8.44.

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

TỪ KHÓA LIÊN QUAN