亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > MySQL > 正文

詳細講述MySQL中的子查詢操作

2024-07-24 13:06:59
字體:
來源:轉載
供稿:網友

這篇文章主要介紹了詳細講述MySQL中的子查詢操作,文中也給出了具體的代碼實例講解,需要的朋友可以參考下

繼續做以下的前期準備工作:

新建一個測試數據庫TestDB;

 

 
  1. create database TestDB; 

創建測試表table1和table2;

 

 
  1. CREATE TABLE table1 
  2. customer_id VARCHAR(10) NOT NULL
  3. city VARCHAR(10) NOT NULL
  4. PRIMARY KEY(customer_id) 
  5. )ENGINE=INNODB DEFAULT CHARSET=UTF8; 
  6.  
  7. CREATE TABLE table2 
  8. order_id INT NOT NULL auto_increment, 
  9. customer_id VARCHAR(10), 
  10. PRIMARY KEY(order_id) 
  11. )ENGINE=INNODB DEFAULT CHARSET=UTF8; 

插入測試數據;

 

 
  1. INSERT INTO table1(customer_id,city) VALUES('163','hangzhou'); 
  2. INSERT INTO table1(customer_id,city) VALUES('9you','shanghai'); 
  3. INSERT INTO table1(customer_id,city) VALUES('tx','hangzhou'); 
  4. INSERT INTO table1(customer_id,city) VALUES('baidu','hangzhou'); 
  5.  
  6. INSERT INTO table2(customer_id) VALUES('163'); 
  7. INSERT INTO table2(customer_id) VALUES('163'); 
  8. INSERT INTO table2(customer_id) VALUES('9you'); 
  9. INSERT INTO table2(customer_id) VALUES('9you'); 
  10. INSERT INTO table2(customer_id) VALUES('9you'); 
  11. INSERT INTO table2(customer_id) VALUES('tx'); 

準備工作做完以后,table1和table2看起來應該像下面這樣:

 

 
  1. mysql> select * from table1; 
  2. +-------------+----------+ 
  3. | customer_id | city | 
  4. +-------------+----------+ 
  5. | 163 | hangzhou | 
  6. | 9you | shanghai | 
  7. | baidu | hangzhou | 
  8. | tx | hangzhou | 
  9. +-------------+----------+ 
  10. rows in set (0.00 sec) 
  11.  
  12. mysql> select * from table2; 
  13. +----------+-------------+ 
  14. | order_id | customer_id | 
  15. +----------+-------------+ 
  16. | 1 | 163 | 
  17. | 2 | 163 | 
  18. | 3 | 9you | 
  19. | 4 | 9you | 
  20. | 5 | 9you | 
  21. | 6 | tx | 
  22. +----------+-------------+ 
  23. rows in set (0.00 sec) 

準備工作做的差不多了,開始今天的總結吧。

一個問題

現在需要查詢所有杭州用戶的所有訂單號,這個SQL語句怎么寫?首先,你可以這么寫:

 

 
  1. select table2.customer_id, table2.order_id from table2 join table1 on table1.customer_id=table2.customer_id where table1.city='hangzhou'

能實現我們需要的結果。但是,我們也可以這么寫:

 

 
  1. select customer_id, order_id from table2 where customer_id in (select customer_id from table1 where city='hangzhou'); 

呃?在()括號中的的select語句是什么?問題來了,這到底是什么語法,怎么也可以完成任務,那么這篇博文就圍繞著這個問題開始展開。

啥是子查詢

簡單的說,子查詢就是:

詳細講述MySQL中的子查詢操作

如上圖所示,子查詢,有叫內部查詢,相對于內部查詢,包含內部查詢的就稱為外部查詢。子查詢可以包含普通select可以包括的任何子句,比如:distinct、group by、order by、limit、join和union等;但是對應的外部查詢必須是以下語句之一:select、insert、update、delete、set或者do。

詳細講述MySQL中的子查詢操作

我們可以在where和having子句中使用子查詢,將子查詢得到的結果作為判斷的條件。

使用比較進行子查詢

一個子查詢會返回一個標量(就一個值)、一個行、一個列或一個表,這些子查詢稱之為標量、行、列和表子查詢。

當一個子查詢返回一個標量時,我們就可以在where或者having子句中使用比較符與子查詢得到的結果進行直接判斷。比如,我現在要得到比用戶tx訂單數多的customer_id、city和訂單數,這個sql語句怎么寫。

先來說說,我寫sql的一般步驟:

讀懂需求;

得到比用戶tx訂單數多的customer_id、city和對應的訂單數。

看看最終需要得到哪些字段信息;

最終需要得到customer_id、city和訂單數信息。

分析這些字段信息涉及到哪幾個表;

涉及到表table1和表table2。

這幾個表是如何關聯的;

表table1和表table2的關聯就在于customer_id字段。

分解需求,得到一個個小的需求;

需要得到tx用戶的訂單數;

需要得到其它用戶的訂單數;

比較訂單數。

確認每一個小需求的過濾條件;

得到每個小需求的結果,進行組裝,得到最終結果。

最終,我會寫出一下的sql語句:

 

 
  1. select table1.customer_id,city,count(order_id)  
  2. from table1 join table2  
  3. on table1.customer_id=table2.customer_id  
  4. where table1.customer_id <> 'tx' 
  5. group by customer_id  
  6. having count(order_id) >  
  7. (select count(order_id)  
  8. from table2  
  9. where customer_id='tx' 
  10. group by customer_id); 

上面的查詢中使用了子查詢,外部查詢與子查詢得到的結果進行了比較判斷。如果子查詢返回一個標量值(就一個值),那么外部查詢就可以使用:=、>、<、>=、<=和<>符號進行比較判斷;如果子查詢返回的不是一個標量值,而外部查詢使用了比較符和子查詢的結果進行了比較,那么就會拋出異常。

使用ANY進行子查詢

上面使用比較符進行子查詢,規定了子查詢只能返回一個標量值;但是,如果子查詢返回的是一個集合,怎么辦?

沒問題,我們可以使用:any、in、some或者all來和子查詢的返回結果進行條件判斷。這里先總結使用any進行子查詢。

any關鍵詞必須與上面總結的比較操作符一起使用;any關鍵詞的意思是“對于子查詢返回的列中的任何一個數值,如果比較結果為TRUE,就返回TRUE”。

好比“10 >any(11, 20, 2, 30)”,由于10>2,所以,該該判斷會返回TRUE;只要10與集合中的任意一個進行比較,得到TRUE時,就會返回TRUE。

比如,我現在要查詢比customer_id為tx或者9you的訂單數量多的用戶的id、城市和訂單數量。

我可以得到以下的sql語句來完成需求。

 

 
  1. select table1.customer_id,city,count(order_id) 
  2. from table1 join table2 
  3. on table1.customer_id=table2.customer_id 
  4. where table1.customer_id<>'tx' and table1.customer_id<>'9you' 
  5. group by customer_id 
  6. having count(order_id) > 
  7. any ( 
  8. select count(order_id) 
  9. from table2 
  10. where customer_id='tx' or customer_id='9you' 
  11. group by customer_id); 

any的意思比較好明白,直譯就是任意一個,只要條件滿足任意的一個,就返回TRUE。

使用IN進行子查詢

使用in進行子查詢,這個我們在日常寫sql的時候是經常遇到的。in的意思就是指定的一個值是否在這個集合中,如何在就返回TRUE;否則就返回FALSE了。

in是“=any”的別名,在使用“=any”的地方,我們都可以使用“in”來進行替換。這里就不舉例了,盡情的發揮想象,自行發揮吧。

有了in,肯定就有了not in;not in并不是和<>any是同樣的意思,not in和<>all是一個意思,關于all,下面馬上就要總結了。

使用SOME進行子查詢

some是any的別名,用的比較少。只需要理解any的意思就好了,這里就不做過多的總結。具體請參考上面的any部分的總結。

使用ALL進行子查詢

all必須與比較操作符一起使用。all的意思是“對于子查詢返回的列中的所有值,如果比較結果為TRUE,則返回TRUE”。

好比“10 >all(2, 4, 5, 1)”,由于10大于集合中的所有值,所以這條判斷就返回TRUE;而如果為“10 >all(20, 3, 2, 1, 4)”,這樣的話,由于10小于20,所以該判斷就會返回FALSE。

<>all的同義詞是not in,表示不等于集合中的所有值,這個很容易和<>any搞混,平時多留點心就好了。

標量子查詢

根據子查詢返回值的數量,將子查詢可以分為標量子查詢和多值子查詢。在使用比較符進行子查詢時,就要求必須是標量子查詢;如果是多值子查詢時,使用比較符,就會拋出異常。

多值子查詢

與標量子查詢對應的就是多值子查詢了,多值子查詢會返回一列、一行或者一個表,它們組成一個集合。我們一般使用的any、in、all和some等詞,將外部查詢與子查詢的結果進行判斷。如果將any、in、all和some等詞與標量子查詢,就會得到空的結果。

獨立子查詢

獨立子查詢是不依賴外部查詢而運行的子查詢。什么叫依賴外部查詢?先看下面兩個sql語句。

sql語句1:獲得所有hangzhou顧客的訂單號。

 

 
  1. select order_id  
  2. from table2  
  3. where customer_id in 
  4. (select customer_id  
  5. from table1  
  6. where city='hangzhou'); 

sql語句2:獲得城市為hangzhou,并且存在訂單的用戶。

 

 
  1. select *  
  2. from table1  
  3. where city='hangzhou' and exists 
  4. (select *  
  5. from table2  
  6. where table1.customer_id=table2.customer_id); 

上面的兩條sql語句,雖然例子舉的有點不是很恰當,但是足以說明這里的問題了。

對于sql語句1,我們將子查詢單獨復制出來,也是可以單獨執行的,就是子查詢與外部查詢沒有任何關系。

對于sql語句2,我們將子查詢單獨復制出來,就無法單獨執行了,由于sql語句2的子查詢依賴外部查詢的某些字段,這就導致子查詢就依賴外部查詢,就產生了相關性。

對于子查詢,很多時候都會考慮到效率的問題。當我們執行一個select語句時,可以加上explain關鍵字,用來查看查詢類型,查詢時使用的索引以及其它等等信息。比如這么用:

 

 
  1. explain select order_id  
  2. from table2  
  3. where customer_id in 
  4. (select customer_id  
  5. from table1  
  6. where city='hangzhou'); 

使用獨立子查詢,如果子查詢部分對集合的最大遍歷次數為n,外部查詢的最大遍歷次數為m時,我們可以記為:O(m+n)。而如果使用相關子查詢,它的遍歷次數可能會達到O(m+m*n)??梢钥吹?,效率就會成倍的下降;所以,大伙在使用子查詢時,一定要考慮到子查詢的相關性。

關于explain的更多解釋,請參考這里。

相關子查詢

相關子查詢是指引用了外部查詢列的子查詢,即子查詢會對外部查詢的每行進行一次計算。但是在MySQL的內部,會進行動態優化,會隨著情況的不同會有所不同。使用相關子查詢是最容易出現性能的地方。而關于sql語句的優化,這又是一個非常大的話題了,只能通過實際的經驗積累,才能更好的去理解如何進行優化。

關于sql的性能,我這里不能說什么,如果只是閱讀其它人的文章來考慮性能問題,其實是沒有任何感覺的,我們需要實際的項目中才能更好的理解。

EXISTS謂詞

EXISTS是一個非常牛叉的謂詞,它允許數據庫高效地檢查指定查詢是否產生某些行。根據子查詢是否返回行,該謂詞返回TRUE或FALSE。與其它謂詞和邏輯表達式不同的是,無論輸入子查詢是否返回行,EXISTS都不會返回UNKNOWN,對于EXISTS來說,UNKNOWN就是FALSE。還是上面的語句,獲得城市為hangzhou,并且存在訂單的用戶。

 

 
  1. select *  
  2. from table1  
  3. where city='hangzhou' and exists 
  4. (select *  
  5. from table2  
  6. where table1.customer_id=table2.customer_id); 

使用explain查看一下,就會得到以下內容:

詳細講述MySQL中的子查詢操作

我們可以很明顯的看到,存在一個相關的子查詢(DEPENDENT SUBQUERY)??梢钥吹紼XISTS和IN是非常相似的,那么它們之間的區別是什么呢?

關于IN和EXISTS的主要區別在于三值邏輯的判斷上。EXISTS總是返回TRUE或FALSE,而對于IN,除了TRUE、FALSE值外,還有可能對NULL值返回UNKNOWN。但是在過濾器中,UNKNOWN的處理方式與FALSE相同,因此使用IN與使用EXISTS一樣,SQL優化器會選擇相同的執行計劃。

說到了IN和EXISTS幾乎是一樣的,但是,就不得不說到NOT IN和NOT EXISTS,對于輸入列表中包含NULL值時,NOT EXISTS和NOT IN之間的差異就表現的非常大了。輸入列表包含NULL值時,IN總是返回TRUE和UNKNOWN,因此NOT IN就會得到NOT TRUE和NOT UNKNOWN,即FALSE和UNKNOWN。

 

 
  1. mysql> select 'c' NOT IN ('a''b'NULL)/G; 

執行一下上述代碼,看看結果。你就會感到驚訝。

派生表

上面也說到了,在子查詢返回的值中,也可能返回一個表,如果將子查詢返回的虛擬表再次作為FROM子句的輸入時,這就子查詢的虛擬表就成為了一個派生表。語法結構如下:

 

 
  1. FROM (subquery expression) AS derived_table_alias 

由于派生表是完全的虛擬表,并沒有也不可能被物理地具體化。

總結

總算總結的差不多了,當然了子查詢的東西還是有很多的,不可能一篇文章就能總結的完的,這里只是把一些基本的概念,常用的知識點進行了總結,關于將子查詢使用到update、delete和insert語句中的用法,我這里并沒有涉及,大體上都是大同小異的。知識這個東西,展開了,就沒有頭了,還是需要適可而止,適當的進行深度的挖掘,但是深度最好不要超過2,關于這個2如何定義,自行把握。好了,這篇文章就到此為止了,我們下一篇見。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲国产成人精品久久| 91久久精品国产91久久性色| 一级做a爰片久久毛片美女图片| 国产精品吊钟奶在线| 欧美精品电影免费在线观看| 欧美日韩中文字幕| 精品中文字幕视频| 麻豆一区二区在线观看| 久久中文字幕在线| 国产女人18毛片水18精品| 久久久99免费视频| 欧美一性一乱一交一视频| 国产精品一久久香蕉国产线看观看| 亚洲 日韩 国产第一| 51午夜精品视频| 538国产精品一区二区免费视频| 亚洲最大av网| 久久五月天色综合| 国产在线一区二区三区| 日韩中文字幕网址| 最近免费中文字幕视频2019| 亚洲成av人片在线观看香蕉| 亚洲黄色av网站| 亚洲人精选亚洲人成在线| 欧美精品在线视频观看| 欧美大尺度激情区在线播放| 在线观看免费高清视频97| 日韩精品久久久久| 欧美精品一本久久男人的天堂| 欧美劲爆第一页| 亚洲人成网在线播放| 欧美激情va永久在线播放| 成人午夜在线视频一区| 国产欧美日韩91| 一本色道久久88精品综合| 国内精品久久久久久久久| 亚洲精品成人久久电影| 2019日本中文字幕| 国产精品久久不能| 亚洲人成在线免费观看| 日韩精品中文字幕视频在线| 性欧美在线看片a免费观看| 精品欧美激情精品一区| 亚洲欧美变态国产另类| 91极品女神在线| 尤物九九久久国产精品的特点| 久久久久久久亚洲精品| 国产91网红主播在线观看| 日韩毛片在线观看| 国产精品美女999| 91社区国产高清| 亚洲天堂视频在线观看| 亚洲精品电影网在线观看| 亚洲天堂av在线免费观看| 亚洲 日韩 国产第一| 欧美成人精品在线观看| 亚洲国产精品久久久久秋霞不卡| 精品人伦一区二区三区蜜桃免费| 亚洲一区二区三区在线视频| 久久99亚洲热视| 欧美理论电影在线观看| 午夜精品蜜臀一区二区三区免费| 国产精品欧美激情在线播放| 国产精品一久久香蕉国产线看观看| 欧美在线xxx| 一区二区成人精品| 欧美裸体男粗大视频在线观看| 久久天天躁狠狠躁夜夜躁| 欧美在线视频在线播放完整版免费观看| 欧日韩不卡在线视频| 欧美激情中文网| 亚洲精品不卡在线| 国内免费精品永久在线视频| 亚洲男人天堂网站| 亚洲国产精品人人爽夜夜爽| 色综合久久久久久中文网| 亚洲三级av在线| 欧美另类xxx| 日韩中文在线观看| 欧美电影电视剧在线观看| 亚洲成人在线网| 日韩欧美国产骚| 日韩综合视频在线观看| 欧美性高跟鞋xxxxhd| 亚洲精品色婷婷福利天堂| 精品国产91久久久| 视频在线一区二区| 精品久久久视频| 欧美极品欧美精品欧美视频| 亚洲精品99久久久久中文字幕| 日日噜噜噜夜夜爽亚洲精品| 91精品久久久久久久久中文字幕| 欧美在线影院在线视频| 亚洲伦理中文字幕| 91精品久久久久久久久| 国产69精品久久久久99| 欧美激情综合亚洲一二区| 国产福利精品在线| 97精品国产aⅴ7777| 久久亚洲欧美日韩精品专区| 一区二区成人精品| 欧美激情va永久在线播放| 97在线观看免费高清| 欧美一区深夜视频| 成人福利视频在线观看| 亚洲欧美精品在线| 国产精品美女久久久久av超清| 久久久精品2019中文字幕神马| 成人黄色片网站| 精品夜色国产国偷在线| 91精品中文在线| 68精品国产免费久久久久久婷婷| 精品小视频在线| 91在线中文字幕| 91在线免费视频| 日韩av在线免费看| 亚洲精品国产精品自产a区红杏吧| 亚洲一级一级97网| 日韩欧美一区二区三区久久| 欧美激情视频在线免费观看 欧美视频免费一| 欧美日韩国产中文字幕| 亚洲精品久久7777777| 亚洲а∨天堂久久精品喷水| 97在线视频免费观看| 性色av一区二区三区| 日韩av电影免费观看高清| 黑人与娇小精品av专区| 国产亚洲精品久久久久动| 中文字幕日韩精品在线观看| 性色av一区二区三区| 亚洲国产精品va在线看黑人| 黑人巨大精品欧美一区二区免费| 日韩精品小视频| 色老头一区二区三区在线观看| 久久久日本电影| 成人欧美在线视频| 日韩在线视频免费观看高清中文| 精品亚洲一区二区三区四区五区| 日韩在线不卡视频| 久久韩剧网电视剧| 日韩成人中文字幕| 欧美猛交免费看| 久久伊人色综合| 91在线免费观看网站| 国产日韩欧美在线播放| 欧美国产日本高清在线| 久久大大胆人体| 亚洲欧洲成视频免费观看| 国产成人在线视频| 欧美午夜美女看片| 97视频在线观看播放| 国产成人高潮免费观看精品| 欧美视频免费在线观看| 欧美精品午夜视频| 在线亚洲欧美视频| 亚洲免费伊人电影在线观看av| www.xxxx精品| 欧美精品在线免费观看| 欧美日本中文字幕| 国内伊人久久久久久网站视频| 欧美性xxxx在线播放| 精品无码久久久久久国产| 91视频-88av| 久久精品99久久久久久久久|