⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch07.htm

📁 Learn SQL in an easy way...
💻 HTM
📖 第 1 页 / 共 3 页
字号:
LE SHOPPE  HOMETOWN   KS     54678      555-1278    NONEAAA BIKE   10 OLDTOWN NE     56784      555-3421    JOHN-MGRJACKS BIKE 24 EGLIN   FL     34567      555-2314    NONE</FONT></PRE><P>with a slightly modified version of the query you used to find the above-averageorders:</P><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF"><B>SELECT ALL C.NAME, C.ADDRESS, C.STATE,C.ZIPFROM CUSTOMER CWHERE C.NAME IN(SELECT O.NAMEFROM ORDERS O, PART PWHERE O.PARTNUM = P.PARTNUMANDO.QUANTITY * P.PRICE  &gt;(SELECT AVG(O.QUANTITY * P.PRICE)FROM ORDERS O, PART PWHERE O.PARTNUM = P.PARTNUM))</B>NAME       ADDRESS    STATE  ZIP========== ========== ====== ==========BIKE SPEC  CPT SHRIVE LA     45678LE SHOPPE  HOMETOWN   KS     54678JACKS BIKE 24 EGLIN   FL     34567</FONT></PRE><H5>ANALYSIS:</H5><P>Here's a look at what you asked for. In the innermost set of parentheses, youfind a familiar statement:</P><PRE><FONT COLOR="#0066FF">SELECT AVG(O.QUANTITY * P.PRICE)FROM ORDERS O, PART PWHERE O.PARTNUM = P.PARTNUM</FONT></PRE><P>This result feeds into a slightly modified version of the <TT>SELECT</TT> clauseyou used before:</P><PRE><FONT COLOR="#0066FF">SELECT O.NAMEFROM ORDERS O, PART PWHERE O.PARTNUM = P.PARTNUMANDO.QUANTITY * P.PRICE  &gt;(...)</FONT></PRE><P>Note the <TT>SELECT</TT> clause has been modified to return a single column, <TT>NAME</TT>,which, not so coincidentally, is common with the table <TT>CUSTOMER</TT>. Runningthis statement by itself you get:</P><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF"><B>SELECT O.NAMEFROM ORDERS O, PART PWHERE O.PARTNUM = P.PARTNUMANDO.QUANTITY * P.PRICE  &gt;(SELECT AVG(O.QUANTITY * P.PRICE)FROM ORDERS O, PART PWHERE O.PARTNUM = P.PARTNUM)</B>NAME==========LE SHOPPEBIKE SPECLE SHOPPEBIKE SPECJACKS BIKE</FONT></PRE><H5>ANALYSIS:</H5><P>We just spent some time discussing why your subqueries should return just onevalue. The reason this query was able to return more than one value becomes apparentin a moment.</P><P>You bring these results to the statement:</P><PRE><FONT COLOR="#0066FF">SELECT C.NAME, C.ADDRESS, C.STATE,C.ZIPFROM CUSTOMER CWHERE C.NAME IN</FONT></PRE><PRE><FONT COLOR="#0066FF">(...)</FONT></PRE><H5>ANALYSIS:</H5><P>The first two lines are unremarkable. The third reintroduces the keyword <TT>IN</TT>,last seen on Day 2, &quot;Introduction to the Query: The <TT>SELECT</TT> Statement.&quot;<TT>IN</TT> is the tool that enables you to use the multiple-row output of your subquery.<TT>IN</TT>, as you remember, looks for matches in the following set of values enclosedby parentheses, which in the this case produces the following values:</P><PRE><FONT COLOR="#0066FF">LE SHOPPEBIKE SPECLE SHOPPEBIKE SPECJACKS BIKE</FONT></PRE><P>This subquery provides the conditions that give you the mailing list:</P><PRE><FONT COLOR="#0066FF">NAME       ADDRESS    STATE  ZIP========== ========== ====== ======BIKE SPEC  CPT SHRIVE LA     45678LE SHOPPE  HOMETOWN   KS     54678JACKS BIKE 24 EGLIN   FL     34567</FONT></PRE><P>This use of <TT>IN</TT> is very common in subqueries. Because <TT>IN</TT> usesa set of values for its comparison, it does not cause the SQL engine to feel conflictedand inadequate.</P><P>Subqueries can also be used with <TT>GROUP BY</TT> and <TT>HAVING</TT> clauses.Examine the following query:</P><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF"><B>SELECT NAME, AVG(QUANTITY)FROM ORDERSGROUP BY NAMEHAVING AVG(QUANTITY) &gt;(SELECT AVG(QUANTITY)FROM ORDERS)</B>NAME               AVG========== ===========BIKE SPEC            8JACKS BIKE          14</FONT></PRE><H5>ANALYSIS:</H5><P>Let's examine this query in the order the SQL engine would. First, look at thesubquery:</P><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF"><B>SELECT AVG(QUANTITY)FROM ORDERS</B>        AVG===========          6</FONT></PRE><P>By itself, the query is as follows:</P><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF"><B>SELECT NAME, AVG(QUANTITY)FROM ORDERSGROUP BY NAME</B>NAME               AVG========== ===========AAA BIKE             6BIKE SPEC            8JACKS BIKE          14LE SHOPPE            4TRUE WHEEL           5</FONT></PRE><P>When combined through the <TT>HAVING</TT> clause, the subquery produces two rowsthat have above-average <TT>QUANTITY</TT>.</P><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF"><B>HAVING AVG(QUANTITY) &gt;(SELECT AVG(QUANTITY)FROM ORDERS)</B>NAME               AVG========== ===========BIKE SPEC            8JACKS BIKE          14</FONT></PRE><H2><FONT COLOR="#000077">Correlated Subqueries</FONT></H2><P>The subqueries you have written so far are <I>self-contained</I>. None of themhave used a reference from outside the subquery. <I>Correlated subqueries</I> enableyou to use an outside reference with some strange and wonderful results. Look atthe following query:</P><H5>INPUT:</H5><PRE><FONT COLOR="#0066FF"><B>SELECT *FROM ORDERS OWHERE 'ROAD BIKE' =(SELECT DESCRIPTIONFROM PART PWHERE P.PARTNUM = O.PARTNUM)</B></FONT></PRE><H5><FONT COLOR="#000000">OUTPUT:</FONT></H5><PRE><FONT COLOR="#000000"></FONT></PRE><PRE><FONT COLOR="#0066FF">  ORDEREDON NAME           PARTNUM    QUANTITY REMARKS=========== ========== =========== =========== ==========19-MAY-1996 TRUE WHEEL          76           3 PAID17-JAN-1996 BIKE SPEC           76          11 PAID17-JAN-1996 LE SHOPPE           76           5 PAID 1-JUL-1996 AAA BIKE            76           4 PAID</FONT></PRE><PRE><FONT COLOR="#0066FF">11-JUL-1996 JACKS BIKE          76          14 PAID</FONT></PRE><P>This query actually resembles the following <TT>JOIN</TT>:</P><H5>INPUT:</H5><PRE><FONT COLOR="#0066FF"><B>SELECT O.ORDEREDON, O.NAME,O.PARTNUM, O.QUANTITY, O.REMARKSFROM ORDERS O, PART PWHERE P.PARTNUM = O.PARTNUMAND P.DESCRIPTION = 'ROAD BIKE'</B></FONT></PRE><H5><FONT COLOR="#000000">OUTPUT:</FONT></H5><PRE><FONT COLOR="#0066FF">  ORDEREDON NAME           PARTNUM    QUANTITY REMARKS=========== ========== =========== =========== =======19-MAY-1996 TRUE WHEEL          76           3 PAID 1-JUL-1996 AAA BIKE            76           4 PAID17-JAN-1996 LE SHOPPE           76           5 PAID17-JAN-1996 BIKE SPEC           76          11 PAID11-JUL-1996 JACKS BIKE          76          14 PAID</FONT></PRE><H5>ANALYSIS:</H5><P>In fact, except for the order, the results are identical. The correlated subqueryacts very much like a join. The correlation is established by using an element fromthe query in the subquery. In this example the correlation was established by thestatement</P><PRE><FONT COLOR="#0066FF">WHERE P.PARTNUM = O.PARTNUM</FONT></PRE><P>in which you compare <TT>P.PARTNUM</TT>, from the table inside your subquery,to <TT>O.PARTNUM</TT>, from the table outside your query. Because <TT>O.PARTNUM</TT>can have a different value for every row, the correlated subquery is executed foreach row in the query. In the next example each row in the table <TT>ORDERS</TT></P><H5><FONT COLOR="#000000">INPUT/OUTPUT:</FONT></H5><PRE><FONT COLOR="#0066FF"><B>SELECT *FROM ORDERS</B>  ORDEREDON NAME           PARTNUM    QUANTITY REMARKS=========== ========== =========== =========== =======15-MAY-1996 TRUE WHEEL          23           6 PAID19-MAY-1996 TRUE WHEEL          76           3 PAID 2-SEP-1996 TRUE WHEEL          10           1 PAID30-JUN-1996 TRUE WHEEL          42           8 PAID30-JUN-1996 BIKE SPEC           54          10 PAID30-MAY-1996 BIKE SPEC           10           2 PAID30-MAY-1996 BIKE SPEC           23           8 PAID17-JAN-1996 BIKE SPEC           76          11 PAID17-JAN-1996 LE SHOPPE           76           5 PAID 1-JUN-1996 LE SHOPPE           10           3 PAID 1-JUN-1996 AAA BIKE            10           1 PAID 1-JUL-1996 AAA BIKE            76           4 PAID 1-JUL-1996 AAA BIKE            46          14 PAID11-JUL-1996 JACKS BIKE          76          14 PAID</FONT></PRE><P>is processed against the subquery criteria:</P><PRE><FONT COLOR="#0066FF">SELECT DESCRIPTIONFROM PART PWHERE P.PARTNUM = O.PARTNUM</FONT></PRE><H5>ANALYSIS:</H5><P>This operation returns the <TT>DESCRIPTION</TT> of every row in <TT>PART</TT>where <TT>P.PARTNUM = O.PARTNUM</TT>. These descriptions are then compared in the<TT>WHERE</TT> clause:</P><PRE><FONT COLOR="#0066FF">WHERE 'ROAD BIKE' =</FONT></PRE><P>Because each row is examined, the subquery in a correlated subquery can have morethan one value. However, don't try to return multiple columns or columns that don'tmake sense in the context of the <TT>WHERE</TT> clause. The values returned stillmust match up against the operation specified in the <TT>WHERE</TT> clause. For example,in the query you just did, returning the <TT>PRICE</TT> to compare with <TT>ROADBIKE</TT> would have the following result:</P><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF"><B>SELECT *FROM ORDERS OWHERE 'ROAD BIKE' =(SELECT PRICEFROM PART PWHERE P.PARTNUM = O.PARTNUM)</B></FONT></PRE><PRE><FONT COLOR="#0066FF">conversion error from string &quot;ROAD BIKE&quot;</FONT></PRE><P>Here's another example of something not to do:</P><PRE><FONT COLOR="#0066FF">SELECT *FROM ORDERS OWHERE 'ROAD BIKE' =(SELECT *FROM PART PWHERE P.PARTNUM = O.PARTNUM)</FONT></PRE><H5>ANALYSIS:</H5><P>This <TT>SELECT</TT> caused a General Protection Fault on my Windows operatingsystem. The SQL engine simply can't correlate all the columns in <TT>PART</TT> withthe operator <TT>=</TT>.</P><P>Correlated subqueries can also be used with the <TT>GROUP BY</TT> and <TT>HAVING</TT>clauses. The following query uses a correlated subquery to find the average totalorder for a particular part and then applies that average value to filter the totalorder grouped by <TT>PARTNUM</TT>:</P><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF"><B>SELECT O.PARTNUM, SUM(O.QUANTITY*P.PRICE), COUNT(PARTNUM)FROM ORDERS O, PART PWHERE P.PARTNUM = O.PARTNUMGROUP BY O.PARTNUMHAVING SUM(O.QUANTITY*P.PRICE) &gt;(SELECT AVG(O1.QUANTITY*P1.PRICE)FROM PART P1, ORDERS O1WHERE P1.PARTNUM = O1.PARTNUMAND P1.PARTNUM = O.PARTNUM)</B>    PARTNUM         SUM       COUNT=========== =========== ===========         10     8400.00           4         23     4906.30           2         76    19610.00           5</FONT></PRE><H5>ANALYSIS:</H5><P>The subquery does not just compute one</P><PRE><FONT COLOR="#0066FF">AVG(O1.QUANTITY*P1.PRICE)</FONT></PRE><P>Because of the correlation between the query and the subquery,</P><PRE><FONT COLOR="#0066FF">AND P1.PARTNUM = O.PARTNUM</FONT></PRE><P>this average is computed for every group of parts and then compared:</P><PRE><FONT COLOR="#0066FF">HAVING SUM(O.QUANTITY*P.PRICE) &gt;</FONT></PRE><BLOCKQUOTE>	<P><HR><FONT COLOR="#000077"><B>TIP:</B></FONT><B> </B>When using correlated subqueries	with <TT>GROUP BY</TT> and <TT>HAVING</TT>, the columns in the <TT>HAVING</TT> clause	must exist in either the <TT>SELECT</TT> clause or the <TT>GROUP BY</TT> clause.	Otherwise, you get an error message along the lines of <TT>invalid column reference</TT>	because the subquery is evoked for each group, not each row. You cannot make a valid	comparison to something that is not used in forming the group. <HR></BLOCKQUOTE><H2><FONT COLOR="#000077">Using EXISTS, ANY, and ALL</FONT></H2><P>The usage of the keywords <TT>EXISTS</TT>, <TT>ANY</TT>, and <TT>ALL</TT> is notintuitively obvious to the casual observer. <TT>EXISTS</TT> takes a subquery as anargument and returns <TT>TRUE</TT> if the subquery returns anything and <TT>FALSE</TT>if the result set is empty. For example:</P><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF"><B>SELECT NAME, ORDEREDONFROM ORDERS WHERE EXISTS(SELECT *FROM ORDERSWHERE NAME ='TRUE WHEEL')</B>NAME         ORDEREDON========== ===========TRUE WHEEL 15-MAY-1996TRUE WHEEL 19-MAY-1996TRUE WHEEL  2-SEP-1996TRUE WHEEL 30-JUN-1996BIKE SPEC  30-JUN-1996BIKE SPEC  30-MAY-1996BIKE SPEC  30-MAY-1996BIKE SPEC  17-JAN-1996LE SHOPPE  17-JAN-1996LE SHOPPE   1-JUN-1996

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -