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

SQL VISUAL QUICKSTART GUIDE- P33 pdf

10 215 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 182,25 KB

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

Nội dung

For example, change Listing 8.57 to: SELECT DISTINCT ‘Yes’ AS “Duplicates?” FROM SYSIBM.SYSDUMMY1 WHERE EXISTS SELECT 1 FROM authors GROUP BY au_id HAVING COUNT* > 1; In MySQL, to run Li

Trang 1

■ Although I use SELECT COUNT(*)in some

of the DBMS-specific subqueries in the

DBMS Tip in this section, you should be

wary of using an aggregate function in

a subquery’s SELECTclause The existence

test in Listing 8.59, for example, always is

true because COUNT(*)always will return

a row (with the value zero here) I could

argue that the result, Figure 8.59, is

flawed logically because no publisher ID

XXX exists

■ To run Listings 8.55, 8.57, and

8.58 in Microsoft Access,

change SELECT *toSELECT 1 Additionally,

in Listing 8.57 add the clause FROM authors

to the outer query, and in Listing 8.58

add the clause FROM title_authorsto

the outer query

To run Listings 8.57 and 8.58 in Oracle,

add the clause FROM DUALto the outer

query; see the DBMS Tip in “Creating

Derived Columns” in Chapter 5

To run Listings 8.55, 8.57, and 8.58 in

DB2, change SELECT *toSELECT 1

Additionally, in Listings 8.57 and 8.58,

add the clause FROM SYSIBM.SYSDUMMY1to

the outer query; see the DBMS Tip in

“Creating Derived Columns” in Chapter

5 For example, change Listing 8.57 to:

SELECT DISTINCT ‘Yes’ AS

“Duplicates?”

FROM SYSIBM.SYSDUMMY1

WHERE EXISTS

(SELECT 1

FROM authors GROUP BY au_id HAVING COUNT(*) > 1);

In MySQL, to run Listing 8.57 add the

clause FROM authorsto the outer query, and in Listing 8.58 add the clause FROM title_authorsto the outer query MySQL 4.0 and earlier don’t support subqueries; see the DBMS Tip in “Understanding Subqueries” earlier in this chapter

To run Listings 8.55, 8.57, and 8.58 in

PostgreSQL, change SELECT *toSELECT 1 Chapter 8

Listing 8.59 Be careful when using aggregate

functions in a subquery SELECT clause See Figure 8.59 for the result.

SELECT pub_id FROM publishers WHERE EXISTS

(SELECT COUNT(*)

FROM titles WHERE pub_id = ' XXX ');

Listing

pub_id -P01 P02 P03 P04

Figure 8.59 The result of Listing 8.59.

Trang 2

Comparing Equivalent Queries

As you’ve seen in this chapter and the pre-ceding one, you can express the same query

in different ways (different syntax, same semantics) To expand on this point, I’ve written the same query six semantically equivalent ways Each of the statements in

Listing 8.60 lists the authors who have

written (or cowritten) at least one book

See Figure 8.60 for the result.

The first two queries (inner joins) will run

at the same speed as one another Of the third through sixth queries (which use sub-queries), the last one probably is the worst performer The DBMS will stop processing the other subqueries as soon as it encounters

a single matching value But the subquery

in the last statement has to count all the matching rows before it returns either true

or false Your DBMS’s optimizer should run the inner joins at about the same speed as the fastest subquery statement

You might find this programming flexibility

to be attractive, but people who design DBMS optimizers don’t, because they’re tasked with considering all the possible ways to express a query, figuring out which one per-forms best, and reformulating your query internally to its optimal form (Entire careers are devoted to solving these types of opti-mization problems.) If your DBMS has a flawless optimizer, it will run all six of the queries in Listing 8.60 at the same speed But that situation is unlikely, so you’ll have to experiment with your DBMS to see which version runs fastest

Listing 8.60 These six queries are equivalent

semantically; they all list the authors who have

written (or cowritten) at least one book See

Figure 8.60 for the result.

SELECT DISTINCT a.au_id

FROM authors a

ON a.au_id = ta.au_id;

SELECT DISTINCT a.au_id

FROM authors a, title_authors ta

SELECT au_id

FROM authors a

WHERE au_id IN

(SELECT au_id

FROM title_authors);

SELECT au_id

FROM authors a

WHERE au_id = ANY

(SELECT au_id

FROM title_authors);

SELECT au_id

FROM authors a

WHERE EXISTS

(SELECT *

FROM title_authors ta

WHERE a.au_id = ta.au_id);

SELECT au_id

FROM authors a

WHERE 0 <

(SELECT COUNT(*)

FROM title_authors ta

WHERE a.au_id = ta.au_id);

Listing

au_id

-A01

A02

A03

A04

A05

A06

Figure 8.60 Each of the six statements in Listing 8.60

returns this result.

Trang 3

✔ Tips

■ You should compare queries against large

test tables (more than 10,000 or even

100,000 rows) so that speed and memory

differences will be obvious

■ DBMSs provide tools to let

you measure the efficiency of

queries Tables 8.4 and 8.5 list the

com-mands that time queries and show their

execution plans.

Chapter 8

Table 8.4

Timing Queries

D B M S C o m m a n d

Access Not available SQL Server SET STATISTICS TIME ON Oracle SET TIMING ON

MySQL The mysql command-line utility

prints execution times by default PostgreSQL \timing

Table 8.5

Showing Query Execution Plans

D B M S C o m m a n d

Access Not available SQL Server SET SHOWPLAN_TEXT ON Oracle EXPLAIN PLAN DB2 EXPLAIN or db2expln

PostgreSQL EXPLAIN

SQL Tuning

After you learn the basics of SQL, your next step is to tune your SQL statements so that they run efficiently, which means learning about your DBMS’s optimizer Performance tuning involves some platform-independent general principles, but the most effective tuning relies

on the idiosyncrasies of the specific DBMS Tuning is beyond the scope of this book, but the

internet has plenty of discussion groups and articles—search for tuning (or performance or

optimization) together with the name of your DBMS.

A good book to get started with is Peter Gulutzan and Trudy Pelzer’s SQL Performance

Tuning (Addison-Wesley), which covers eight DBMSs, or Dan Tow’s SQL Tuning (O’Reilly),

which covers Microsoft SQL Server, Oracle, and DB2 If you look up one of these books on Amazon.com, you can find other tuning books by clicking the Similar Items link

Trang 4

Recall from Chapter 2 that set theory is fundamental to the relational model But whereas mathematical sets are unchanging, database sets are dynamic—they grow, shrink, and otherwise change over time This chapter covers the following SQL set operators, which combine the results of two SELECTstatements into one result:

◆ UNIONreturns all the rows returned by both queries, with duplicates removed

◆ INTERSECTreturns all rows common to both queries (that is, all distinct rows retrieved by both queries)

◆ EXCEPTreturns all rows from the first query without the rows that appear in the second query, with duplicates removed

These set operations aren’t joins, but you can mix and chain them to combine two or more tables

Set Operations

9

Trang 5

Combining Rows with UNION

AUNIONoperation combines the results of two

queries into a single result that has the rows

returned by both queries (This operation

differs from a join, which combines columns

from two tables.) AUNIONexpression removes

duplicate rows from the result; a UNION ALL

expression doesn’t remove duplicates

Unions are simple, but they have some

restrictions:

◆ TheSELECT-clause lists in the two queries

must have the same number of columns

(column names, arithmetic expressions,

aggregate functions, and so on)

◆ The corresponding columns in the two

queries must be listed in the same order

in the two queries

◆ The corresponding columns must have

the same data type or must be implicitly

convertible to the same type

◆ If the names of corresponding columns

match, that column name is used in the

result If the corresponding column names

differ, it’s up to the DBMS to determine

the column name in the result Most

DBMSs take the result’s column names

from the first individual query in the

UNIONstatement If you want to rename a

column in the result, use an ASclause in

the first query; see “Creating Column

Aliases with AS” in Chapter 4

◆ An ORDER BYclause can appear in only

the final query in the UNIONstatement

The sort is applied to the final, combined

result Because the result’s column

names depend on the DBMS, it’s often

easiest to use relative column positions

to specify the sort order; see “Sorting

Rows with ORDER BY” in Chapter 4

◆ GROUP BYandHAVINGcan be specified in

the individual queries only; they can’t be

used to affect the final result

Chapter 9

Listing 9.1 List the states where authors and

publishers are located See Figure 9.1 for the result.

SELECT state FROM authors

UNION

SELECT state FROM publishers;

Listing

state -NULL CA CO FL NY

Figure 9.1 Result of Listing 9.1.

Listing 9.2 List the states where authors and

publishers are located, including duplicates See Figure 9.2 for the result.

SELECT state FROM authors

UNION ALL

SELECT state FROM publishers;

Listing

state -NY CO CA CA NY CA FL NY CA NULL CA

Figure 9.2 Result of Listing 9.2.

Trang 6

To combine rows:

◆ Type:

select_statement1

UNION [ALL]

select_statement2;

select_statement1 and select_statement2

are SELECTstatements The number and the order of the columns must be identi-cal in both statements, and the data types of corresponding columns must be compatible Duplicate rows are eliminated from the result unless ALLis specified

Listing 9.1 lists the states where authors

and publishers are located By default, UNION removes duplicate rows from the result See

Figure 9.1 for the result.

Listing 9.2 is the same as Listing 9.1 except

that it includes the ALLkeyword, so all rows are included in the results, and duplicates

aren’t removed See Figure 9.2 for the result.

Listing 9.3 lists the names of all the authors

and publishers The ASclause in the first query names the column in the result The ORDER BYclause uses a relative column posi-tion instead of a column name to sort the

result See Figure 9.3 for the result.

Listing 9.3 List the names of all the authors and

publishers See Figure 9.3 for the result.

SELECT au_fname || ' ' || au_lname AS "Name"

FROM authors

UNION

SELECT pub_name

FROM publishers

ORDER BY 1 ASC;

Listing

Name

-Kellsey

Abatis Publishers

Christian Kells

Core Dump Books

Hallie Hull

Klee Hull

Paddy O'Furniture

Sarah Buchman

Schadenfreude Press

Tenterhooks Press

Wendy Heydemark

Figure 9.3 Result of Listing 9.3.

Trang 7

Listing 9.4 expands on Listing 9.3 and

defines the extra column Type to identify

which table each row came from The

WHERE conditions retrieve the authors and

publishers from New York state only See

Figure 9.4 for the result.

Listing 9.5 adds a third query to Listing 9.4

to retrieve the titles of books published in

New York state also See Figure 9.5 for

the result

Listing 9.6 is similar to Listing 9.5 except

that it lists the counts of each author,

pub-lisher, and book, instead of their names

See Figure 9.6 for the result.

Chapter 9

Listing 9.4 List the names of all the authors and

publishers located in New York state, sorted by type and then by name See Figure 9.4 for the result.

SELECT 'author' AS "Type", au_fname || ' ' || au_lname AS "Name", state

FROM authors WHERE state = 'NY'

UNION

SELECT 'publisher', pub_name, state FROM publishers WHERE state = 'NY' ORDER BY 1 ASC, 2 ASC;

Listing

Type Name state -author Christian Kells NY author Sarah Buchman NY publisher Abatis Publishers NY

Figure 9.4 Result of Listing 9.4.

Trang 8

Listing 9.5 List the names of all the authors and

publishers located in New York state and the titles

of books published in New York state, sorted by type

and then by name See Figure 9.5 for the result.

SELECT

'author' AS "Type",

au_fname || ' ' || au_lname AS "Name"

FROM authors

WHERE state = 'NY'

UNION

SELECT

'publisher',

pub_name

FROM publishers

WHERE state = 'NY'

UNION

SELECT

'title',

title_name

FROM titles t

INNER JOIN publishers p

ON t.pub_id = p.pub_id

WHERE p.state = 'NY'

ORDER BY 1 ASC, 2 ASC;

Listing

Type Name

-

-author Christian Kells

author Sarah Buchman

publisher Abatis Publishers

title 1977!

title How About Never?

title Not Without My Faberge Egg

title Spontaneous, Not Annoying

Figure 9.5 Result of Listing 9.5.

Listing 9.6 List the counts of all the authors and

publishers located in New York state and the titles

of books published in New York state, sorted by type See Figure 9.6 for the result.

SELECT 'author' AS "Type", COUNT(au_id) AS "Count"

FROM authors WHERE state = 'NY'

UNION

SELECT 'publisher', COUNT(pub_id) FROM publishers WHERE state = 'NY'

UNION

SELECT 'title', COUNT(title_id) FROM titles t INNER JOIN publishers p

ON t.pub_id = p.pub_id WHERE p.state = 'NY' ORDER BY 1 ASC;

Listing

Type Count -author 2 publisher 1 title 4

Figure 9.6 Result of Listing 9.6.

Trang 9

In Listing 9.7, I revisit Listing 5.30 in

“Evaluating Conditional Values with CASE”

in Chapter 5 But instead of using CASEto

change book prices and simulate if-then

logic, I use multiple UNIONqueries See

Figure 9.7 for the result.

Chapter 9

Listing 9.7 Raise the price of history books by

10 percent and psychology books by 20 percent, and leave the prices of other books unchanged See Figure 9.7 for the result.

SELECT title_id, type, price,

FROM titles WHERE type = 'history' UNION

SELECT title_id, type, price, price * 1.20

FROM titles WHERE type = 'psychology' UNION

SELECT title_id, type, price, price

FROM titles WHERE type NOT IN ('psychology','history')

ORDER BY type ASC, title_id ASC;

Listing

title_id type price New price - - - -T06 biography 19.95 19.95 T07 biography 23.95 23.95 T10 biography NULL NULL T12 biography 12.99 12.99 T08 children 10.00 10.00 T09 children 13.95 13.95 T03 computer 39.95 39.95 T01 history 21.99 24.19 T02 history 19.95 21.95 T13 history 29.99 32.99 T04 psychology 12.99 15.59 T05 psychology 6.95 8.34 T11 psychology 7.99 9.59

Figure 9.7 Result of Listing 9.7.

In theory, the order in which the SELECT

statements (tables) occur in a UNION

should make no speed difference But

in practice your DBMS might run

small_table1

UNION

small_table2

UNION

big_table;

faster than

small_table1

UNION

big_table

UNION

small_table2;

because of the way the optimizer merges

intermediate results and removes

duplicate rows The results are DBMS

dependent Experiment

Trang 10

✔ Tips

■ UNIONis a commutative operation:

A UNION Bis the same as B UNION A

■ The SQL standard gives INTERSECThigher

precedence than UNIONandEXCEPT, but

your DBMS might use a different order

Use parentheses to specify order of

eval-uation in queries with mixed set operators;

see “Determining the Order of Evaluation”

in Chapter 5

■ Don’t use UNIONwhere a compound

con-dition will suffice:

SELECT DISTINCT * FROM mytable

WHERE col1 = 1 AND col2 = 2;

usually is faster than

SELECT * FROM mytable

WHERE col1 = 1;

UNION

SELECT * FROM mytable

WHERE col2 = 2;

■ If you mixUNIONandUNION ALLin a

single statement, use parentheses to

specify order of evaluation Take these

two statements, for example:

SELECT * FROM table1

UNION ALL

(SELECT * FROM table2

UNION

SELECT * FROM table3);

and:

(SELECT * FROM table1

UNION ALL

SELECT * FROM table2)

UNION

SELECT * FROM table3;

The first statement eliminates duplicates in

the union of table2 and table3 but doesn’t

eliminate duplicates in the union of that

result and table1 The second statement includes duplicates in the union of table1 and table2 but eliminates duplicates in the subsequent union with table3, so ALL has no effect on the final result of this statement

■ For UNIONoperations, the DBMS per-forms an internal sort to identify and remove duplicate rows; hence, the result

of a UNIONmight be sorted even if you don’t specify an ORDER BYclause UNION ALLdoesn’t sort because it doesn’t need

to remove duplicates Sorting is compu-tationally expensive—don’t use UNION when UNION ALLwill suffice

Microsoft SQL Server, use +

to concatenate strings (see “Concatenating Strings with ||” in Chapter 5) To run Listings 9.3 through 9.5, change the con-catenation expressions to:

au_fname + ‘ ‘ + au_lname

In MySQL, use CONCAT()to concatenate strings (see “Concatenating Strings with

||” in Chapter 5) To run Listings 9.3 through 9.5, change the concatenation expressions to:

CONCAT(au_fname, ‘ ‘, au_lname)

In older PostgreSQL versions, convert

the floating-point numbers in Listing 9.7

toDECIMAL; see “Converting Data Types with CAST()” in Chapter 5 To run Listing 9.7, change new-price calcula-tions to:

price * CAST((1.10) AS DECIMAL) price * CAST((1.20) AS DECIMAL)

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

TỪ KHÓA LIÊN QUAN