Answer to Chapter 10 of O'Reilly Learning Sql on SQL Server 2005

 

10.6. Review Questions
1. What is a noncorrelated subquery?

A noncorrelated subquery is a subquery that is independent of the outer query. In other words,

the subquery could be executed on its own.
 
2. Which type of subquery can be executed on its own?
They do not have information from outer query.

3. Which part of a query is evaluated first, the query or the subquery?
For correlated subquery, query is done first.


4. What are correlated subqueries?
 correlated subquery is an inner subquery whose information is referenced by the main, outer

query such that the inner query may be thought of as being executed repeatedly.

5. What does the EXISTS predicate do?
EXISTS predicate seeks only to find whether the subquery WHERE can be satisfied.

6. What are considered universal qualifiers?
In SQL, "for all" and "for each" are the universal qualifiers, whereas "there exists" is the

existential qualifier.

7. Is correlation necessary when we use EXISTS? Why?
correlation is usually necessary with EXISTS. EXISTS only return a status.


8. Explain how the "for all" type SQL query involves a double-nested correlated subquery

using the NOT EXISTS predicate.
 
10.7. Exercises
Unless specified otherwise, use the Student_course database to answer the following questions.

Also, use appropriate column headings when displaying your output.
1. List the names of students who have received Cs. Do this in three ways: (a) as a join,

(b) as an uncorrelated subquery, and (c) as a correlated subquery. Show both results and

account for any differences.

SELECT DISTINCT s.SNAME, g.GRADE
FROM Student s INNER JOIN Grade_report g
ON s.STNO = g.STUDENT_NUMBER
WHERE g.GRADE = 'C'
-- Without DISTINCT, one name will shows many times.

SELECT  s.SNAME
FROM Student s
WHERE s.STNO in ( SELECT g.STUDENT_NUMBER
 FROM Grade_report g
 WHERE g.GRADE = 'C')


SELECT  s.SNAME
FROM Student s
WHERE EXISTS ( SELECT 1
 FROM Grade_report g
 WHERE g.GRADE = 'C' and g.STUDENT_NUMBER = s.STNO)

 

2. In section "Existence Queries and Correlation," you were asked to find the names of

students who have taken a computer science class and earned a grade of B. We noted that it

could be done in several ways. One query could look like this:
SELECT   s.sname
FROM     Student s
WHERE    s.stno IN
   (SELECT  gr.student_number
    FROM    Grade_report gr, Section
    WHERE   Section.section_id =  gr.section_id
    AND         Section.course_num LIKE 'COSC____'
    AND         gr.grade = 'B')

Redo this query, putting the finding of the COSC course in a correlated subquery. The query

should be as follows:
The Student table uncorrelated subquery to the Grade_report table, correlated EXISTS to the

Section table.


SELECT   s.sname
FROM     Student s
WHERE    s.stno IN
   (SELECT  gr.student_number
    FROM    Grade_report gr
    WHERE   gr.grade = 'B'
    AND EXISTS (
   SELECT 1
   FROM Section
   WHERE   Section.section_id =  gr.section_id
   AND         Section.course_num LIKE 'COSC____')
   )

3. In the section "SQL Universal and Existential Qualifiers," we illustrated both an

existence query:
SELECT  s.sname
FROM    Student s
WHERE EXISTS
  (SELECT 'X'
   FROM     Grade_report gr
   WHERE    s.stno = gr.student_number
   AND      gr.grade = 'C')

and a NOT EXISTS version:
SELECT   s.sname
FROM     Student s
WHERE NOT EXISTS
  (SELECT 'X'
   FROM     Grade_report gr
   WHERE    s.stno = gr.student_number
   AND      gr.grade = 'C')

Show that the EXISTS version is the complement of the NOT EXISTS versioncount the rows in the

EXISTS result, the rows in the NOT EXISTS result, and the rows in the Student table. Also,

devise a query to give the same result with IN and NOT..IN.

SELECT  s.sname
FROM    Student s
WHERE s.stno IN
  (SELECT gr.student_number
   FROM     Grade_report gr
   WHERE    gr.grade = 'C')

SELECT  s.sname
FROM    Student s
WHERE s.stno NOT IN
  (SELECT gr.student_number
   FROM     Grade_report gr
   WHERE    gr.grade = 'C')

4. Discover whether all students take courses by counting the students, and then count

those students whose student numbers are in the Grade_report table and those whose student

numbers are not in the table. Use IN and then NOT..IN, and then use EXISTS and NOT EXISTS. How

many students take courses and how many students do not?


 
SELECT   COUNT(s.STNO) as [cnt in student]
FROM     Student s

SELECT COUNT(GR.STUDENT_NUMBER) as [all grade rows],
  COUNT(DISTINCT gr.STUDENT_NUMBER) as [all student in grade report]
FROM Grade_report gr

SELECT COUNT(s.STNO) as [count in grade table]
FROM Student s
WHERE s.STNO IN
(SELECT gr.STUDENT_NUMBER FROM Grade_report gr)

SELECT COUNT(s.STNO) as [count without grade table]
FROM Student s
WHERE s.STNO NOT IN
(SELECT gr.STUDENT_NUMBER FROM Grade_report gr)

SELECT COUNT(s.STNO) as [count in grade table]
FROM Student s
WHERE  EXISTS
(SELECT 1 FROM Grade_report gr
WHERE gr.STUDENT_NUMBER = s.STNO)

SELECT COUNT(s.STNO) as [count in grade table]
FROM Student s
WHERE  NOT EXISTS
(SELECT 1 FROM Grade_report gr
WHERE gr.STUDENT_NUMBER = s.STNO)

a. Find out which students have taken courses but who have not taken COSC courses. Create

a set of student names and courses from the Student, Grade_report, and Section tables (use the

prefix COSC to indicate computer science courses). Then, use NOT..IN to "subtract" from that

set another set of student names of students (who take courses) who have taken COSC courses.

For this set difference, use NOT..IN.

 

SELECT DISTINCT st.SNAME
FROM Student st, Grade_report gr
WHERE gr.STUDENT_NUMBER = st.STNO
  AND gr.STUDENT_NUMBER NOT IN
 (
 SELECT gr1.STUDENT_NUMBER
 FROM Section sc,Grade_report gr1
 WHERE sc.SECTION_ID = gr1.SECTION_ID
   AND sc.COURSE_NUM Like 'COSC%'
)


b. Change NOT..IN to NOT EXISTS (with other appropriate changes) and explain the result.

The "other appropriate changes" include adding the correlation and the change of the result

column in the subquery set.

SELECT DISTINCT st.SNAME
FROM Student st, Grade_report gr
WHERE gr.STUDENT_NUMBER = st.STNO
  AND NOT EXISTS
 (
 SELECT 1
 FROM Section sc,Grade_report gr1
 WHERE sc.SECTION_ID = gr1.SECTION_ID
  AND gr1.STUDENT_NUMBER = st.STNO
   AND sc.COURSE_NUM Like 'COSC%'
)

5. There exists a table called Plants. List the table and then find out what company or

companies have plants in all cities. Verify your result manually.

SELECT company, plantlo
FROM Plants x
WHERE NOT EXISTS
 (SELECT 'X'
  FROM Plants y
  WHERE NOT EXISTS
  (SELECT 'Y'
   FROM Plants z
   WHERE x.COMPANY = z.COMPANY
   AND y.PLANTLO = z.PLANTLO
   )
  )

 

6. Run the following query and print the result:
SELECT distinct name, langu
FROM Cap x
WHERE NOT EXISTS
              (SELECT 'X'
              FROM Cap y
              WHERE NOT EXISTS
                          (SELECT 'X'
                          FROM Cap z
                          WHERE X.langu =Z.langu
                          AND Y.name=Z.name))

Save the query (e.g., save forall) and hand in the result.
a. Recreate the Cap table (e.g., call it some other name, such as LANG1). To do this,

first create the table and then use the INSERT statement with the sub select option (INSERT

INTO LANG1 AS SELECT * FROM Cap).
b. Add a new person to your table who speaks only BENG.
c. Recall your previous SELECT (get for all).
d. CHANGE the table from CAP to LANG1 (for all occurrences, use CHANGE/Cap/lang1/

repeatedly, assuming that you called your table LANG1).
e. Start the new query (the one you just created with LANG1 in it).
f. How is this result different from the situation in which Newperson was not in LANG1?

Provide an explanation of why the query did what it did.

 

7. The Department_to_major table is a list of four-letter department codes with the

department names. In Chapter 8, Exercise 7 (hereafter referred to as Exercise 8-7), you

created a table called Secretary, which should now have data like this:
Secretary 
dCode Name
ACCT Beryl
COSC Kaitlyn
ENGL David
HIST Christina
BENG Fred
Null Brenda

In Exercise 8-7, you did the following:
1. Create a query that lists the names of departments that have secretaries (use IN and

the Secretary table in a subquery). Save this query as q8_7a.

SELECT *
FROM Department_to_major d
WHERE d.Dcode IN
 ( SELECT s.dcode
   FROM Secretary s )

2. Create a query that lists the names of departments that do not have secretaries (use

NOT..IN). Save this query as q8_7b.

SELECT *
FROM Department_to_major d
WHERE d.Dcode NOT IN
 ( SELECT s.dcode
   FROM Secretary s
   WHERE s.dcode IS NOT NULL)

3. Add one more row to the Secretary table that contains <null,'Brenda'>. (This could be

a situation in which you have hired Brenda but have not yet assigned her to a department.)
4. Recall q8_7a and rerun it.
5. Recall q8_7b and rerun it.
We remarked in Exercise 8-7 that the NOT..IN predicate has problems with nulls: the behavior

of NOT..IN when nulls exist may surprise you. If nulls may exist in the subquery, then NOT..IN

should not be used. If you use NOT..IN in a subquery, you must ensure that nulls will not

occur in the subquery or you must use some other predicate, such as NOT EXISTS. Perhaps the

best advice is to avoid NOT..IN.
Here, we repeat Exercise 8-7 using NOT EXISTS:

8. Reword query q8_7a to use EXISTS. You will have to correlate the inner and outer

queries. Save this query as q10_7aa.
SELECT *
FROM Department_to_major d
WHERE EXISTS
 ( SELECT 1
   FROM Secretary s
   WHERE s.dcode = d.Dcode )


9. Reword query q8_7b to use NOT EXISTS. You will have to correlate the inner and outer

queries. Save this query as q10_7bb. You should not have a phrase IS NOT NULL in your NOT

EXISTS query.
SELECT *
FROM Department_to_major d
WHERE  NOT EXISTS
 ( SELECT 1
   FROM Secretary s
   WHERE s.dcode = d.Dcode)

10. Rerun q8_9a with and without <null, Brenda>.
11. Rerun q8_9b with and without <null, Brenda>.
Note the difference in behavior versus the original question. List the names of those

departments that do or do not have secretaries. The point here is to encourage you to use NOT

EXISTS in a correlated subquery, rather than NOT..IN.
 
 
 

你可能感兴趣的:(sql,sql,server,report,table,query,subquery)