[SQL] SQL 基礎知識梳理(五) - 復雜查詢


SQL 基礎知識梳理(五) - 復雜查詢

 

目錄

  • 視圖
  • 子查詢
  • 關聯子查詢

 

一、視圖

  1.視圖和表

    (1)視圖:從 SQL 的角度來看視圖就是一張表。

    (2)視圖和表的區別:是否保存了實際的數據。數據庫中的數據實際上保存到計算機的存儲設備(如硬盤);視圖實際上保存的是 SELECT 語句,從視圖中讀取數據時,視圖會在內部執行該 SELETC 語句並創建出一張臨時表。

    (3)視圖的優點

      ①無需保存數據,節省存儲設備的容量。

      ②保存頻繁使用的 SELECT 語句,提高效率。

  【總結】表中存儲的是實際數據,視圖保存的是 SELECT 語句。

  【總結】應該將經常使用的 SELECT 語句做成視圖。

  

  2.創建視圖

--語法
--CREATE VIEW 視圖名稱(<視圖列名1>, <視圖列名2>, ...)
--AS
--<SELECT 語句>
--示例:創建視圖
CREATE VIEW ShohinSum(shohin_bunrui, cnt_shohin)
AS
SELECT shohin_bunrui, COUNT(*)
FROM dbo.Shohin
GROUP BY shohin_bunrui;
--示例:使用視圖
SELECT *
FROM shohinSum;

 

  視圖就是保存好的 SELECT 語句。我們將頻繁的查詢操作保存成視圖,就可以提高效率了。

  

  (1)使用視圖的查詢

    在FROM 子句中使用視圖的查詢,通常有如下步驟:

      ①執行定義視圖的 SELECT 語句;

      ②根據得到的結果,再執行在 FROM 子句中使用視圖的 SELECT 子句。

    也就意味着可能會出現“多重視圖”,我們應盡量避免在視圖的基礎上創建視圖,因為這樣很可能會降低 SQL 的性能。

  【備注】應避免在視圖的基礎上創建視圖。

 

  (2)視圖的限制 - 創建視圖時不能使用 ORDER BY 子句(但可以使用其它 SELECT 子句)

圖:假設這是一個新創建的視圖

 

  (3)視圖的限制 - 更新視圖

圖:假設上圖去掉 ORDER BY 子句,在成功創建 ShohinSm 視圖后,再執行插入時仍然報錯

  【備注】通過聚合得到的視圖不能進行更新。

 

  下面是一個成功創建視圖並可以執行插入語句的示例。

 創建視圖並插入

檢測數據

  雖然可以對視圖實現更新操作,但我們通常不這樣做。

 

  3.刪除視圖

--語法
--DROP VIEW 視圖名稱(<視圖列名1>, <視圖列名2>, ...)
--示例
DROP VIEW shohinSum 

 

二、子查詢

  1.子查詢和視圖:

    (1)子查詢:將用來定義視圖的 SELECT 語句直接用於 FROM 子句當中。

--示例
SELECT shohin_bunrui, cnt_shohin
FROM
(
    SELECT shohin_bunrui, COUNT(*) AS cnt_shohin
    FROM Shohin
    GROUP BY shohin_bunrui
) AS ShohinSum;    --記得加上別名哦

  圖中的 AS ShohinSum 是子查詢的名稱,子查詢(subquery)就是“次級(sub)”的“查詢(query)”。先執行①的內層查詢,再執行②的外層查詢。

  【備注】子查詢作為內層查詢會首先執行。

  子查詢的層數沒有限制,出於性能和可讀性考慮,應避免使用多層嵌套的子查詢。

 

  2.標量子查詢

  上面的子查詢基本上都會返回多行結果(雖然偶爾只返回 1 行數據),而標量子查詢,就是必須而且只能返回 1 行 1 列的結果。

  【備注】標量子查詢就是返回單一值的子查詢。

--示例:查詢出銷售單價高於平均銷售單價的商品,hanbai_tanka:銷售單價 
SELECT *
FROM dbo.Shohin
WHERE hanbai_tanka >
(
    SELECT AVG(hanbai_tanka)
    FROM dbo.Shohin
)

  3.在其它地方書寫標量子查詢

  能夠使用常數或者列名的地方很多:SELECT 子句、GROUP BY 子句、HAVING 子句,或 ORDER BY 子句等。

--示例:在 SELECT 子句中使用標量子查詢
SELECT shohin_id ,
       shohin_mei ,
       hanbai_tanka ,
       (
        SELECT AVG(hanbai_tanka)
        FROM dbo.Shohin
       ) AS avg_hanbai_tanka
    
FROM dbo.Shohin

  

--示例:在 HAVING 子句中使用標量子查詢
SELECT shohin_bunrui,
    AVG(hanbai_tanka)
FROM dbo.Shohin
GROUP BY shohin_bunrui
HAVING AVG(hanbai_tanka) >
(
    SELECT AVG(hanbai_tanka)
    FROM dbo.Shohin
)

  【注意】使用標量子查詢時,該子查詢不能返回多行結果。

 

三、關聯子查詢

  為了直觀顯示字段名,現在將所有列名都改成中文。

CREATE TABLE Shohin
(  
    商品編號   CHAR(4)      NOT NULL,
    商品名稱    VARCHAR(100) NOT NULL,
    商品分類 VARCHAR(32)  NOT NULL,
    銷售單價  INTEGER ,
    進貨單價  INTEGER ,
    登記日期      DATE ,
    PRIMARY KEY (商品編號)
 );

INSERT INTO Shohin VALUES ('0001', 'T恤' ,'衣服', 1000, 500, '2009-09-20');
INSERT INTO Shohin VALUES ('0002', '打孔器', '辦公用品', 500, 320, '2009-09-11');
INSERT INTO Shohin VALUES ('0003', '運動T恤', '衣服', 4000, 2800, NULL);
INSERT INTO Shohin VALUES ('0004', '菜刀', '廚房用具', 3000, 2800, '2009-09-20');
INSERT INTO Shohin VALUES ('0005', '高壓鍋', '廚房用具', 6800, 5000, '2009-01-15');
INSERT INTO Shohin VALUES ('0006', '叉子', '廚房用具', 500, NULL, '2009-09-20');
INSERT INTO Shohin VALUES ('0007', '擦菜板', '廚房用具', 880, 790, '2008-04-28');
INSERT INTO Shohin VALUES ('0008', '圓珠筆', '辦公用品', 100, NULL, '2009-11-11');
建表語句:CREATE TABLE Shohin

 

  1.普通子查詢和關聯子查詢的區別

  思考:選取出各商品分類中高於該分類平均銷售單價的商品?

圖 因為內部的子查詢不是前一節中的標量子查詢(這里返回三行結果),所以報錯

  【備注】在 WHERE 子句中使用子查詢時,該子查詢的結果必須為單一值。

--正確的語句:采用關聯子查詢
SELECT *
FROM dbo.Shohin s1
WHERE 銷售單價 >
(
    SELECT AVG(s2.銷售單價) AS avg_銷售單價
    FROM dbo.Shohin s2
    WHERE s1.商品分類 = s2.商品分類
    GROUP BY s2.商品分類
) 

  圖

  關鍵作用的語句:在子查詢中添加的 WHERE 子句的條件。該條件的意思是:在同種商品中對個商品的銷售單價和平均銷售單價作比較。

  

  2.結合條件一定要寫在子查詢 

  圖:把關聯條件移到子查詢之外

  這里涉及到關聯名稱的作用域。子查詢內部設定的關聯名稱,只能在該子查詢內部使用。也可以這樣說:“內部可以看到外部,而外部看不到內部”。

 

備注

  這里采用 MS SQL Server 進行驗證,不保證所有的 DBMS 執行結果正確。

 

《SQL 基礎知識梳理》系列

  《SQL 基礎知識梳理(一) - 數據庫與 SQL

  《SQL 基礎知識梳理(二) - 查詢基礎

  《SQL 基礎知識梳理(三) - 聚合和排序

  《SQL 基礎知識梳理(四) - 數據更新

  《SQL 基礎知識梳理(五) - 復雜查詢

  《SQL 基礎知識梳理(六)- 函數、謂詞、CASE 表達式

  《SQL 基礎知識梳理(七)- 集合運算

 

 


【博主】反骨仔

【原文】http://www.cnblogs.com/liqingwen/p/5939796.html 

【參考】《SQL ゼロからはじめるデータベース操作》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM