《SQL必知必會(huì)》第 11 課 使用子查詢

目標(biāo):

11.1 子查詢

11.2 利用子查詢進(jìn)行過(guò)濾

11.3 作為計(jì)算字段使用子查詢




11.1 子查詢

查詢(query)任何 SQL 語(yǔ)句都是查詢嘿架。但此術(shù)語(yǔ)一般指 SELECT 語(yǔ)句医男。

SQL 還允許創(chuàng)建子查詢(subquery)而柑,即嵌套在其他查詢中的查詢吠卷。

11.2 利用子查詢進(jìn)行過(guò)濾

要求:假如需要列出訂購(gòu)物品 RGAN01 的所有顧客悼潭,應(yīng)該怎樣檢索江解?下

面列出具體的步驟贤牛。

(1) 檢索包含物品 RGAN01 的所有訂單的編號(hào)构蹬。

(2) 檢索具有前一步驟列出的訂單編號(hào)的所有顧客的 ID。

(3) 檢索前一步驟返回的所有顧客 ID 的顧客信息悔据。

SELECT order_num

FROM OrderItems

WHERE prod_id = 'RGAN01';

SELECT cust_id

FROM Orders

WHERE order_num IN (20007,20008);

#嵌套

SELECT cust_id

FROM Orders

WHERE order_num IN (SELECT order_num

????????????????????????????????????????FROM OrderItems

????????????????????????????????????????WHERE prod_id = 'RGAN01');

輸出:# cust_id'1000000004''1000000005'

分析:在 SELECT 語(yǔ)句中庄敛,子查詢總是從內(nèi)向外處理。

SELECT cust_name, cust_contact

FROM Customers

WHERE cust_id IN (SELECT cust_id

???????????????????????????????? FROM Orders

??????????????????????????????? WHERE order_num IN (SELECT order_num

?????????????????????????????????????????????????????????????????????? FROM OrderItems

?????????????????????????????????????????????????????????????????????? WHERE prod_id = 'RGAN01'));

三條SELECT語(yǔ)句

注意:只能是單列

作為子查詢的 SELECT 語(yǔ)句只能查詢單個(gè)列科汗。企圖檢索多個(gè)列將返回錯(cuò)誤藻烤。

注意:子查詢和性能

這里給出的代碼有效,并且獲得了所需的結(jié)果头滔。但是怖亭,使用子查詢并不總是執(zhí)行這類數(shù)據(jù)檢索的最有效方法。

11.3 作為計(jì)算字段使用子查詢

使用子查詢的另一方法是創(chuàng)建計(jì)算字段坤检。假如需要顯示 Customers 表中每個(gè)顧客的訂單總數(shù)兴猩。訂單與相應(yīng)的顧客 ID 存儲(chǔ)在 Orders 表中。

執(zhí)行這個(gè)操作缀蹄,要遵循下面的步驟:

(1) 從 Customers 表中檢索顧客列表峭跳;

(2) 對(duì)于檢索出的每個(gè)顧客,統(tǒng)計(jì)其在 Orders 表中的訂單數(shù)目缺前。

SELECT cust_name, cust_state,

? ? ? ? ? ? ? (SELECT COUNT(*)

? ? ? ? ? ? ?? FROM Orders

? ? ? ? ? ?? ? WHERE Orders.cust_id = Customers.cust_id) AS orders

FROM Customers

ORDER BY cust_name;

子查詢中的 WHERE 子句與前面使用的 WHERE 子句稍有不同蛀醉,因?yàn)樗褂昧送耆薅忻恢皇橇忻╟ust_id)衅码。它指定表名和列名(Orders.cust_id和 Customers.cust_id).

注意:完全限定列名 你已經(jīng)看到了為什么要使用完全限定列名拯刁,沒(méi)有具體指定就會(huì)返回錯(cuò)誤結(jié)果,因?yàn)?DBMS 會(huì)誤解你的意思逝段。有時(shí)候垛玻,由于出現(xiàn)沖突列名而導(dǎo)致的歧義性,會(huì)引起 DBMS 拋出錯(cuò)誤信息奶躯。例如帚桩,WHERE 或 ORDER BY 子句指定的某個(gè)列名可能會(huì)出現(xiàn)在多個(gè)表中。好的做法是嘹黔,如果在SELECT 語(yǔ)句中操作多個(gè)表账嚎,就應(yīng)使用完全限定列名來(lái)避免歧義。

11.4小結(jié)

這一課學(xué)習(xí)了什么是子查詢儡蔓,如何使用它們郭蕉。子查詢常用于 WHERE 子句的 IN 操作符中,以及用來(lái)填充計(jì)算列喂江。我們舉了這兩種操作類型的例子召锈。

-- 11.2 利用子查詢進(jìn)行過(guò)濾

SELECT order_num

FROM OrderItems

WHERE prod_id = 'RGAN01';

SELECT cust_id

FROM Orders

WHERE order_num IN (20007,20008);

SELECT cust_id

FROM Orders

WHERE order_num IN (SELECT order_num

FROM OrderItems

WHERE prod_id = 'RGAN01');

SELECT cust_name, cust_contact

FROM Customers

WHERE cust_id IN (SELECT cust_id

? ? ? ? ? ? ? ? ? FROM Orders

? WHERE order_num IN (SELECT order_num

? FROM OrderItems

? WHERE prod_id = 'RGAN01'));

-- 11.3 作為計(jì)算字段使用子查詢

SELECT cust_name, cust_state,

? ? ? (SELECT COUNT(*)

? ? ? ? FROM Orders

? ? ? ? WHERE Orders.cust_id = Customers.cust_id) AS orders

FROM Customers

ORDER BY cust_name;

11.5挑戰(zhàn)題

1. 使用子查詢,返回購(gòu)買價(jià)格為 10 美元或以上產(chǎn)品的顧客列表获询。你需要使用 OrderItems 表查找匹配的訂單號(hào)(order_num)涨岁,然后使用Order 表檢索這些匹配訂單的顧客 ID(cust_id)拐袜。

SELECT cust_id,cust_name

FROM orders

WHERE order_num IN(SELECT order_num

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? FROM orderitems

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? WHERE item_price>=10 );

2. 你想知道訂購(gòu) BR01 產(chǎn)品的日期。編寫 SQL 語(yǔ)句梢薪,使用子查詢來(lái)確定哪些訂單(在 OrderItems 中)購(gòu)買了 prod_id 為 BR01 的產(chǎn)品阻肿,然后從 Orders 表中返回每個(gè)產(chǎn)品對(duì)應(yīng)的顧客 ID(cust_id)和訂單日期(order_date)。按訂購(gòu)日期對(duì)結(jié)果進(jìn)行排序沮尿。

SELECT cust_id,order_date

FROM Orders

WHERE order_num IN (SELECT order_num

? ? ? ? ? ? ? ? ? ? FROM OrderItems

? ? ? ? ? ? ? ? ? ? WHERE prod_id='BR01')

order by order_date;

3. 現(xiàn)在我們讓它更具挑戰(zhàn)性。在上一個(gè)挑戰(zhàn)題较解,返回購(gòu)買 prod_id 為BR01 的產(chǎn)品的所有顧客的電子郵件(Customers 表中的 cust_email)畜疾。提示:這涉及 SELECT 語(yǔ)句,最內(nèi)層的從 OrderItems 表返回 order_num印衔,中間的從 Customers 表返回 cust_id啡捶。

SELECT cust_email,cust_name

FROM customers

WHERE cust_id IN(SELECT cust_id

? ? FROM Orders

? ? ? ? ? ? ? ? WHERE order_num IN (SELECT order_num

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? FROM OrderItems

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? WHERE prod_id='BR01'));

4. 我們需要一個(gè)顧客 ID 列表,其中包含他們已訂購(gòu)的總金額奸焙。編寫 SQL語(yǔ)句瞎暑,返回顧客 ID(Orders 表中的 cust_id),并使用子查詢返回total_ordered 以便返回每個(gè)顧客的訂單總數(shù)与帆。將結(jié)果按金額從大到小排序了赌。提示:你之前已經(jīng)使用 SUM()計(jì)算訂單總數(shù)。

SELECT cust_id,

? ? ? (SELECT SUM(item_price*quantity)

? ? ? ? FROM OrderItems

? ? ? ? WHERE Orders.order_num = OrderItems.order_num) AS total_ordered

FROM Orders

ORDER BY total_ordered DESC;

5. 再來(lái)玄糟。編寫 SQL 語(yǔ)句勿她,從 Products 表中檢索所有的產(chǎn)品名稱(prod_name),以及名為 quant_sold 的計(jì)算列阵翎,其中包含所售產(chǎn)品的總數(shù)(在 OrderItems 表上使用子查詢和 SUM(quantity)檢索)逢并。

SELECT prod_name,

? ? ? (SELECT Sum(quantity)

? ? ? ? FROM OrderItems

? ? ? ? WHERE Products.prod_id=OrderItems.prod_id) AS quant_sold

FROM Products;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市郭卫,隨后出現(xiàn)的幾起案子砍聊,更是在濱河造成了極大的恐慌,老刑警劉巖贰军,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件玻蝌,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡谓形,警方通過(guò)查閱死者的電腦和手機(jī)灶伊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)寒跳,“玉大人聘萨,你說(shuō)我怎么就攤上這事⊥” “怎么了米辐?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵胸完,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我翘贮,道長(zhǎng)赊窥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任狸页,我火速辦了婚禮锨能,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘芍耘。我一直安慰自己址遇,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布斋竞。 她就那樣靜靜地躺著倔约,像睡著了一般。 火紅的嫁衣襯著肌膚如雪坝初。 梳的紋絲不亂的頭發(fā)上浸剩,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音鳄袍,去河邊找鬼绢要。 笑死,一個(gè)胖子當(dāng)著我的面吹牛畦木,可吹牛的內(nèi)容都是我干的袖扛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼十籍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蛆封!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起勾栗,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤惨篱,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后围俘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體砸讳,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年界牡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了簿寂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宿亡,死狀恐怖常遂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挽荠,我是刑警寧澤克胳,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布平绩,位于F島的核電站,受9級(jí)特大地震影響漠另,放射性物質(zhì)發(fā)生泄漏捏雌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一笆搓、第九天 我趴在偏房一處隱蔽的房頂上張望性湿。 院中可真熱鬧,春花似錦满败、人聲如沸窘奏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至领猾,卻和暖如春米同,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背摔竿。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工面粮, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人继低。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓熬苍,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親袁翁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子柴底,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容