<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    J2EE社區

    茍有恒,何必三更起五更眠;
    最無益,只怕一日曝十日寒.
    posts - 241, comments - 318, trackbacks - 0, articles - 16
    本文轉載于:http://dev.csdn.net/article/65/65909.shtm,個人認為比較全面,可以參考復習一下?。?br />  

    SQL 里面最常用的命令是 SELECT 語句,用于檢索數據。語法是:

    SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    * | expression [ AS output_name ] [, ...]
    [ INTO [ TEMPORARY | TEMP ] [ TABLE ] new_table ]
    [ FROM from_item [, ...] ]
    [ WHERE condition ]
    [ GROUP BY expression [, ...] ]
    [ HAVING condition [, ...] ]
    [ { UNION | INTERSECT | EXCEPT [ ALL ] } select ]
    [ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]
    [ FOR UPDATE [ OF class_name [, ...] ] ]
    [ LIMIT { count | ALL } [ { OFFSET | , } start ]]
    

     

    現在我們將通過不同的例子演示 SELECT 語句復雜的語法。用于這些例子的表在 供應商和部件數據庫 里定義。

    1.4.1.1. 簡單的 Select

    這里是一些使用 SELECT 語句的簡單例子:

    Example 1-4. 帶有條件的簡單查詢

    要從表 PART 里面把字段 PRICE 大于 10 的所有記錄找出來, 我們寫出下面查詢:

    SELECT * FROM PART
    WHERE PRICE > 10;
    
    然后得到表:
     PNO |  PNAME  |  PRICE
    -----+---------+--------
    3  |  Bolt   |   15
    4  |  Cam    |   25
    

     

    在 SELECT語句里使用 "*" 將檢索出表中的所有屬性。 如果我們只希望從表 PART 中檢索出屬性 PNAME 和 PRICE, 我們使用下面的語句:

    SELECT PNAME, PRICE
    FROM PART
    WHERE PRICE > 10;
    
    這回我們的結果是:
                          PNAME  |  PRICE
    --------+--------
    Bolt   |   15
    Cam    |   25
    
    請注意 SQL 的 SELECT 語句對應關系演算里面的 "projection" (映射),而不是 "selection"(選擇)(參閱 關系演算 獲取詳細信息)。

     

    WHERE 子句里的條件也可以用關鍵字 OR,AND,和 NOT 邏輯地連接起來:

    SELECT PNAME, PRICE
    FROM PART
    WHERE PNAME = 'Bolt' AND
    (PRICE = 0 OR PRICE <= 15);
    
    這樣將生成下面的結果:
     PNAME  |  PRICE
    --------+--------
    Bolt   |   15
    

     

    目標列表和 WHERE 子句里可以使用算術操作。例如, 如果我們想知道如果我們買兩個部件的話要多少錢, 我們可以用下面的查詢:

    SELECT PNAME, PRICE * 2 AS DOUBLE
    FROM PART
    WHERE PRICE * 2 < 50;
    
    這樣我們得到:
     PNAME  |  DOUBLE
    --------+---------
    Screw  |    20
    Nut    |    16
    Bolt   |    30
    
    請注意在關鍵字 AS 后面的 DOUBLE 是第二個列的新名字。 這個技巧可以用于目標列表里的每個元素, 給它們賦予一個在結果列中顯示的新的標題。 這個新的標題通常稱為別名。這個別名不能在該查詢的其他地方使用。

     

     

    1.4.1.2. Joins(連接)

    下面的例子顯示了 SQL 里是如何實現連接的。

    要在共同的屬性上連接三個表 SUPPLIER,PART 和 SELLS, 我們通常使用下面的語句:

    SELECT S.SNAME, P.PNAME
    FROM SUPPLIER S, PART P, SELLS SE
    WHERE S.SNO = SE.SNO AND
    P.PNO = SE.PNO;
    
    而我們得到的結果是:
     SNAME | PNAME
    -------+-------
    Smith | Screw
    Smith | Nut
    Jones | Cam
    Adams | Screw
    Adams | Bolt
    Blake | Nut
    Blake | Bolt
    Blake | Cam
    

     

    在 FROM 子句里,我們為每個關系使用了一個別名, 因為在這些關系間有著公共的命名屬性(SNO 和 PNO)。 現在我們可以區分不同表的公共命名屬性, 只需要簡單的用每個關系的別名加上個點做前綴就行了。 聯合是用與 一個內部聯接 里顯示的同樣的方法計算的。首先算出笛卡兒積 SUPPLIER × PART × SELLS 。然后選出那些滿足 WHERE 子句里給出的條件的記錄 (也就是說,公共命名屬性的值必須相等)。 最后我們映射出除 S.SNAME 和 P.PNAME 外的所有屬性。

    另外一個進行連接的方法是使用下面這樣的 SQL JOIN 語法:

    select sname, pname from supplier
    JOIN sells USING (sno)
    JOIN part USING (pno);
    
    giving again:
     sname | pname
    -------+-------
    Smith | Screw
    Adams | Screw
    Smith | Nut
    Blake | Nut
    Adams | Bolt
    Blake | Bolt
    Jones | Cam
    Blake | Cam
    (8 rows)
    

     

    一個用 JOIN 語法創建的連接表,是一個出現在 FROM 子句里的, 在任何 WHERE,GROUP BY 或 HAVING 子句之前的表引用列表項. 其它表引用,包括表名字或者其它 JOIN 子句,如果用逗號分隔的話, 可以包含在 FROM 子句里. 連接生成的表邏輯上和任何其它在 FROM 子句里列出的表都一樣.

    SQL JOIN 有兩種主要類型,CROSS JOIN (無條件連接) 和條件連接.條件連接還可以根據聲明的 連接條件(ON,USING,或 NATURAL)和它 應用的方式(INNER 或 OUTER 連接)進一步細分.

     

    連接類型

    CROSS JOIN

    { T1 } CROSS JOIN { T2 }

    一個交叉連接(cross join)接收兩個分別有 N 行和 M 行 的表 T1 和 T2,然后返回一個包含交叉乘積 NxM 條記錄的 連接表. 對于 T1 的每行 R1,T2 的每行 R2 都與 R1 連接生成 連接的表行 JR,JR 包含所有 R1 和 R2 的字段. CROSS JOIN 實際上就是一個 INNER JOIN ON TRUE.

    條件 JOIN

    { T1 } [ NATURAL ] [ INNER | { LEFT | RIGHT | FULL } [ OUTER ] ] JOIN { T2 } { ON search condition | USING ( join column list ) }

    一個條件 JOIN 必須通過提供一個(并且只能有一個) NATURAL,ON,或者 USING 這樣的關鍵字來聲明它的 連接條件. ON 子句 接受一個 search condition, 它與一個 WHERE 子句相同.USING 子句接受一個用逗號分隔的 字段名列表,連接表中必須都有這些字段, 并且用那些字段連接這些表,生成的連接表包含每個共有字段 和兩個表的所有其它字段. NATURAL 是 USING 子句的縮寫,它列出兩個表中所有公共 的字段名字.使用 USING 和 NATURAL 的副作用是 每個連接的字段都只有一份拷貝出現在結果表中 (與前面定義的關系演算的 JOIN 相比較).

     

    [ INNER ] JOIN

    對于 T1 的每行 R1,連接成的表在 T2 里都有一行滿 足與 R1 一起的連接條件.

    對于所有 JOIN 而言,INNER 和 OUTER 都是可選的.INNER 是缺?。?LEFT,RIGHT,和 FULL 只用于 OUTER JOIN.

    LEFT [ OUTER ] JOIN

    首先,執行一次 INNER JOIN. 然后,如果 T1 里有一行對任何 T2 的行都不滿足 連接條件,那么返回一個連接行,該行的 T2 的字段 為 null.

    小技巧: 連接成的表無條件地包含 T1 里的所有行.

    RIGHT [ OUTER ] JOIN

    首先,執行一次 INNER JOIN. 然后,如果 T2 里有一行對任何 T1 的行都不滿足 連接條件,那么返回一個連接行,該行的 T1 的字段 為 null.

    小技巧: 連接成的表無條件地包含 T2 里的所有行.

    FULL [ OUTER ] JOIN

    首先,執行一次 INNER JOIN. 然后,如果 T1 里有一行對任何 T2 的行都不滿足 連接條件,那么返回一個連接行,該行的 T1 的字段 為 null. 同樣,如果 T2 里有一行對任何 T1 的行都不滿足 連接條件,那么返回一個連接行,該行的 T2 的字段 為 null.

    小技巧: 連接成的表無條件地擁有來自 T1 的每 一行和來自 T2 的每一行.

    所有 類型的 JOIN 都可以鏈接在一起或者嵌套在一起, 這時 T1T2 都可以是連接生成的表.我們可以使用圓括弧控制 JOIN 的順序,如果我們不主動控制,那么連接順序是從左到右.

    1.4.1.3. 聚集操作符

    SQL 提供以一些聚集操作符(如, AVG,COUNT,SUM,MIN,MAX),這些聚集操作符以一個表達式為參數。 只要是滿足 WHERE 子句的行,就會計算這個表達式, 然后聚集操作符對這個輸入數值的集合進行計算. 通常,一個聚集對整個 SELECT 語句計算的結果是 生成一個結果.但如果在一個查詢里面聲明了分組, 那么數據庫將對每個組進行一次獨立的計算,并且 聚集結果是按照各個組出現的(見下節).

    Example 1-5. 聚集

    果我們想知道表 PART 里面所有部件的平均價格,我們可以使用下面查詢:

    SELECT AVG(PRICE) AS AVG_PRICE
    FROM PART;
    

     

    結果是:

     AVG_PRICE
    -----------
    14.5
    

     

    如果我們想知道在表 PART 里面存儲了多少部件,我們可以使用語句:

    SELECT COUNT(PNO)
    FROM PART;
    
    得到:
     COUNT
    -------
    4
    

     

     

    1.4.1.4. 分組聚集

    SQL 允許我們把一個表里面的記錄分成組。 然后上面描述的聚集操作符可以應用于這些組上 (也就是說,聚集操作符的值不再是對所有聲明的列的值進行操作, 而是對一個組的所有值進行操作。這樣聚集函數是為每個組獨立地進行計算的。)

    對記錄的分組是通過關鍵字 GROUP BY 實現的,GROUP BY 后面跟著一個定義組的構成的屬性列表。 如果我們使用語句 GROUP BY A1, &tdot;, Ak 我們就把關系分成了組,這樣當且僅當兩條記錄在所有屬性 A1, &tdot;, Ak 上達成一致,它們才是同一組的。

    Example 1-6. 聚集

    如果我們想知道每個供應商銷售多少個部件,我們可以這樣寫查詢:

    SELECT S.SNO, S.SNAME, COUNT(SE.PNO)
    FROM SUPPLIER S, SELLS SE
    WHERE S.SNO = SE.SNO
    GROUP BY S.SNO, S.SNAME;
    
    得到:
     SNO | SNAME | COUNT
    -----+-------+-------
    1  | Smith |   2
    2  | Jones |   1
    3  | Adams |   2
    4  | Blake |   3
    

     

    然后我們看一看發生了什么事情。首先生成表 SUPPLIER 和 SELLS 的連接:

     S.SNO | S.SNAME | SE.PNO
    -------+---------+--------
    1   |  Smith  |   1
    1   |  Smith  |   2
    2   |  Jones  |   4
    3   |  Adams  |   1
    3   |  Adams  |   3
    4   |  Blake  |   2
    4   |  Blake  |   3
    4   |  Blake  |   4
    

     

    然后我們把那些屬性 S.SNO 和 S.SNAME 相同的記錄放在組中:

     S.SNO | S.SNAME | SE.PNO
    -------+---------+--------
    1   |  Smith  |   1
    |   2
    --------------------------
    2   |  Jones  |   4
    --------------------------
    3   |  Adams  |   1
    |   3
    --------------------------
    4   |  Blake  |   2
    |   3
    |   4
    

     

    在我們的例子里,我們有四個組并且現在我們可以對每個組應用聚集操作符 COUNT,生成上面給出的查詢的最終結果。

     

    請注意如果要讓一個使用 GROUP BY 和聚集操作符的查詢的結果有意義, 那么用于分組的屬性也必須出現在目標列表中。 所有沒有在 GROUP BY 子句里面出現的屬性都只能通過使用聚集函數來選擇。 否則就不會有唯一的數值與其它字段關聯.

    還要注意的是在聚集上聚集是沒有意義的,比如,AVG(MAX(sno)), 因為 SELECT 只做一個回合的分組和聚集.你可以獲得這樣的結果, 方法是使用臨時表或者在 FROM 子句中使用一個子 SELECT 做第一個層次的聚集.

    1.4.1.5. Having

    HAVING 子句運做起來非常象 WHERE 子句, 只用于對那些滿足 HAVING 子句里面給出的條件的組進行計算。 其實,WHERE 在分組和聚集之前過濾掉我們不需要的輸入行, 而 HAVING 在 GROUP 之后那些不需要的組. 因此,WHERE 無法使用一個聚集函數的結果. 而另一方面,我們也沒有理由寫一個不涉及聚集函數的 HAVING. 如果你的條件不包含聚集,那么你也可以把它寫在 WHERE 里面, 這樣就可以避免對那些你準備拋棄的行進行的聚集運算.

    Example 1-7. Having

    如果我們想知道那些銷售超過一個部件的供應商,使用下面查詢:

    SELECT S.SNO, S.SNAME, COUNT(SE.PNO)
    FROM SUPPLIER S, SELLS SE
    WHERE S.SNO = SE.SNO
    GROUP BY S.SNO, S.SNAME
    HAVING COUNT(SE.PNO) > 1;
    
    and get:
     SNO | SNAME | COUNT
    -----+-------+-------
    1  | Smith |   2
    3  | Adams |   2
    4  | Blake |   3
    

     

     

    1.4.1.6. 子查詢

    在 WHERE 和 HAVING 子句里,允許在任何要產生數值的地方使用子查詢 (子選擇)。 這種情況下,該值必須首先來自對子查詢的計算。子查詢的使用擴展了 SQL 的表達能力。

    Example 1-8. 子查詢

    如果我們想知道所有比名為 'Screw' 的部件貴的部件,我們可以用下面的查詢:

    SELECT *
    FROM PART
    WHERE PRICE > (SELECT PRICE FROM PART
    WHERE PNAME='Screw');
    

     

    結果是:

     PNO |  PNAME  |  PRICE
    -----+---------+--------
    3  |  Bolt   |   15
    4  |  Cam    |   25
    

     

    當我們檢查上面的查詢時會發現出現了兩次 SELECT 關鍵字。 第一個在查詢的開頭 - 我們將稱之為外層 SELECT - 而另一個在 WHERE 子句里面,成為一個嵌入的查詢 - 我們將稱之為內層 SELECT。 對外層 SELECT 的每條記錄都必須先計算內層 SELECT。在完成所有計算之后, 我們得知名為 'Screw' 部件的記錄的價格, 然后我們就可以檢查那些價格更貴的記錄了。 (實際上,在本例中,內層查詢只需要執行一次, 因為它不依賴于外層查詢高等狀態.)

    如果我們想知道那些不銷售任何部件的供應商 (比如說,我們想把這些供應商從數據庫中刪除),我們用:

    SELECT *
    FROM SUPPLIER S
    WHERE NOT EXISTS
    (SELECT * FROM SELLS SE
    WHERE SE.SNO = S.SNO);
    

     

    在我們的例子里,結果列將是空的,因為每個供應商至少銷售一個部件。 請注意我們在 WHERE 子句的內層 SELECT 里使用了來自外層 SELECT 的 S.SNO。 正如前面所說的,子查詢為每個外層查詢計算一次,也就是說, S.SNO 的值總是從外層 SELECT 的實際記錄中取得的。

     

    1.4.1.7. 在 FROM 里面的子查詢

    一種有些特別的子查詢的用法是把它們放在 FROM 子句里. 這個特性很有用,因為這樣的子查詢可以輸出多列和多行, 而在表達式里使用的子查詢必須生成一個結果. FROM 里的子查詢還可以讓我們獲得多于一個回合的分組/聚集特性, 而不需要求助于臨時表.

    Example 1-9. FROM 里面的子查詢

    如果我們想知道在所有我們的供應商中的最高平均部件價格的那家, 我們不能用 MAX(AVG(PRICE)),但我們可以這么寫:

    SELECT MAX(subtable.avgprice)
    FROM (SELECT AVG(P.PRICE) AS avgprice
    FROM SUPPLIER S, PART P, SELLS SE
    WHERE S.SNO = SE.SNO AND
    P.PNO = SE.PNO
    GROUP BY S.SNO) subtable;
    
    這個子查詢為每個供應商返回一行(因為它的 GROUP BY) 然后我們在外層查詢對所有行進行聚集.

     

     

    1.4.1.8. Union, Intersect, Except(聯合,相交,相異)

    這些操作符分別計算兩個子查詢產生的元組的聯合,相交和集合理論里的相異。

    Example 1-10. Union, Intersect, Except

    下面的例子是 UNION 的例子:

    SELECT S.SNO, S.SNAME, S.CITY
    FROM SUPPLIER S
    WHERE S.SNAME = 'Jones'
    UNION
    SELECT S.SNO, S.SNAME, S.CITY
    FROM SUPPLIER S
    WHERE S.SNAME = 'Adams';
    
    產生結果:
     SNO | SNAME |  CITY
    -----+-------+--------
    2  | Jones | Paris
    3  | Adams | Vienna
    

     

    下面是相交( INTERSECT)的例子:

    SELECT S.SNO, S.SNAME, S.CITY
    FROM SUPPLIER S
    WHERE S.SNO > 1
    INTERSECT
    SELECT S.SNO, S.SNAME, S.CITY
    FROM SUPPLIER S
    WHERE S.SNO < 3;
    
    產生結果:
     SNO | SNAME |  CITY
    -----+-------+--------
    2  | Jones | Paris
    
    兩個查詢都會返回的元組是那條 SNO=2 的

     

    最后是一個 EXCEPT 的例子:

    SELECT S.SNO, S.SNAME, S.CITY
    FROM SUPPLIER S
    WHERE S.SNO > 1
    EXCEPT
    SELECT S.SNO, S.SNAME, S.CITY
    FROM SUPPLIER S
    WHERE S.SNO > 3;
    
    結果是:
     SNO | SNAME |  CITY
    -----+-------+--------
    2  | Jones | Paris
    3  | Adams | Vienna
    



    名稱: ?4C.ESL | .↗Evon
    口號: 遇到新問題?先要尋找一個方案乄而不是創造一個方案こ
    mail: 聯系我


    Feedback

    # re: SQL select Joins 分組聚集 Having 子查詢 Union Intersect Except 復習  回復  更多評論   

    2009-09-14 10:09 by 于翔
    不錯,學習了

    # re: SQL select Joins 分組聚集 Having 子查詢 Union Intersect Except 復習  回復  更多評論   

    2009-09-15 17:45 by 找個美女做老婆
    Java樂園交流社區(四) 歡迎廣大Javaer加入,大家一起交流,共同進步:
    群號:81107233

    Java樂園學習網站:http://www.javaly.cn
    有大量的學習資料,視頻教程。
    主站蜘蛛池模板: 亚洲AV成人无码天堂| 亚洲国产午夜中文字幕精品黄网站| 国产高清不卡免费视频| 国产亚洲精品免费视频播放| fc2免费人成为视频| 一区二区三区免费在线视频 | 国产小视频免费观看| 全免费a级毛片免费看不卡| 免费无码AV电影在线观看| 黄色成人网站免费无码av| 中文字幕av无码无卡免费| 毛片免费视频观看| 成年女人午夜毛片免费看| 四虎免费在线观看| 免费a级毛片视频| 亚洲精品色婷婷在线影院| 国产亚洲成人在线播放va| 久久九九亚洲精品| 亚洲精品自在线拍| 国产精品久久亚洲不卡动漫| 亚洲AV永久无码精品网站在线观看| 久久精品国产亚洲AV| a级毛片免费观看在线| 久久永久免费人妻精品| 亚洲精品国产免费| 大学生高清一级毛片免费| 亚洲 国产 图片| 国产亚洲精品观看91在线| 亚洲综合一区二区| 亚洲精品自偷自拍无码| 色多多A级毛片免费看| 久久精品免费观看国产| 99精品国产免费久久久久久下载 | 一级毛片不卡免费看老司机| 在线免费观看h片| 成人浮力影院免费看| 手机看片久久国产免费| 亚洲中文字幕无码久久2017| 亚洲高清无在码在线电影不卡| 亚洲欧美日韩一区二区三区| 一级午夜免费视频|