資料庫學習(五)子查詢

小師兄.發表於2019-01-28

子查詢

基本含義

一個select語句,就是一個查詢語句:

select 欄位或表示式 from 資料來源 where XX 條件判斷;

上述select部分,from部分,where部分,往往都是一些“資料”或資料的組合;比如:

from部分,當然就是“表”,或“表的連線結果”,他們也是資料,只是通常為“表資料”;

則,這些資料部分,也可以通過一種“預先”的查詢結果來代替,比如:

如果將該“select 5000”的子查詢語句,替換為“select出來所有商品的平均價”,就具有了現實含義:

可見,所謂子查詢,就是在一個查詢語句(select語句)中的內部,某些位置,又出現的“查詢語句”。

則有兩個概念:

主查詢:

子查詢:

通常,子查詢是為主查詢服務的,而,通常,都是子查詢獲得一定的結果資料之後,才去執行主查詢;

 

在形式上,可以有如下表達:

selelct 欄位或表示式或子查詢 [as 別名] from 表名或連結結果子查詢 where 欄位或表示式或子查詢的條件判斷

即可以在這幾個位置出現子查詢(其中having其實也可以,因為它跟where是一樣含義);

 

按子查詢結果,分為:

表子查詢 :

一個子查詢返回的結果理論上是“多行多列”的時候。此時可以當做一個“表”來使用,通常是放在from後面。

行子查詢 :

一個子查詢返回的結果理論上是“一行多列”的時候。此時可以當做一個“行”來使用,通常放在“行比較語法”中;

行比較語法類似這樣:where row(欄位1,欄位2) = (select 行子查詢)

列子查詢 :

一個子查詢返回的結果理論上是“多行一列”的時候。此時可以當做“多個值”使用,類似這種:(5, 17, 8, 22)。

標量子查詢:

一個子查詢返回的結果理論上是“一行一列”的時候。此時可以當做“一個單個值”使用,類似這種:select 5as c1; 或select ...where a = 17,或select ... where b > 8;即上述“單個資料值”,可以用標量子查詢來代替;

子查詢,按位置(場合)分:

作為主查詢的結果資料

select c1,(select f1 from tab2) as f11 from tab1; #這裡子查詢應該只有一個資料(一行一列,標量子查詢)

作為主查詢的條件資料

select c1 from tab1 where c1 in (select f1 from tab2); #這裡子查詢可以是多個資料(多行一列,列子查詢)

作為主查詢的來源資料:select c1 from (select f1 as c1, f2 from tab2) as t2; #這裡子查詢可以是任意查詢結果(表子查詢)。

常見子查詢

比較運算子中的子查詢

形式:

運算元 比較運算子 (標量子查詢);

說明:

運算元,其實就是比較運算子的2個資料之一而已,通常就是一個欄位名;

select .... from XXX where id > 5;

 

舉例:

找出最高價的商品;

select * from product where price = (select max(price) from product );

 

使用in的子查詢

以前用的in的用法:

XX in (值1,值2,值3,....);

則in子查詢為:

XX in (列子查詢)

舉例:

找出所有類別名稱中帶“電”這個字的所有商品;

可以分兩步思考:

select protype_id from product_type where protype_name like ‘%電%’;

結果為:

然後,將此結果,當做“in”的資料項來使用,去找出商品:

select * from product where protype_id in(

select protype_id from product_type where protype_name like ‘%電%’

);

 

使用any的子查詢

形式:

運算元 比較運算子 any (列子查詢);

含義:

當某個運算元(欄位) 對於該列子查詢的其中任意一個值,滿足該比較運算子,則就算是滿足了條件;

即:只要有一個值滿足,就算是滿足;

進一步解釋:

假設表1(tab1)有資料為:

id, name

1 ‘aa’,

5 ‘bb’

11 ‘cc’

假設表2(tab2)有資料為:

f1 f2

3 ‘x1’

6 ‘x2’

12 ‘x3’

則:

select * from tab1 where id > any (select f1 from tab2);

則可以取出的結果資料有:

5 ‘bb’

11 ‘cc’

使用all的子查詢:

形式:

運算元 比較運算子 all (列子查詢);

含義:

當某個運算元(欄位) 對於該列子查詢的所有資料值,都滿足該比較運算子,才算滿足了條件;

即:要求全部都滿足,才算是滿足;

進一步解釋:

假設表1(tab1)有資料為:

id, name

1 ‘aa’,

5 ‘bb’

11 ‘cc’

假設表2(tab2)有資料為:

f1 f2

3 ‘x1’

6 ‘x2’

12 ‘x3’

則:

select * from tab2 where f1 > all ( select id from tab1 );

結果是:

12 ‘x3’

 

舉例1:

查詢出所有非最高價的商品;

思考第一步:

select price from product;

思考第二步:這些非最高價的商品的價格,只是會小於上述“所有價格”中的某一個;

select * from product where price < any ( select price from product );

舉例2:

查詢出所有最高價的商品;

思考:最高價的商品價格,有一個特徵:大於等於“所有價格”:

select * from product where price >= all ( select price from product );

 

使用some的子查詢

一句話:some是any的同義詞。

 

使用exists的查詢

形式:

where exists( 子查詢 )

含義:

該子查詢如果“有資料”,則exists的結果是true,否則就是false

 

說明:

因為,exists子查詢的該含義,造成主查詢往往出現這樣的情形:要麼全都取出,要麼都不取出。

如果侷限於這個含義(使用情形),其基本就失去了它的現實使用意義。

但:

實際應用中,該子查詢,往往都不是獨立的子查詢,而是會需要跟“主查詢”的資料來源(表),建立某種關係——通常就是連線關係。建立的方式是“隱式的”,即沒有在程式碼上體現關係,但卻在內部有其連線的“實質”。

此隱式連線方式,通常就體現在子查詢中的where條件語句中,使用了主查詢表中的資料(欄位);

 

舉例:

查詢商品表中其類別名稱中帶“電”這個字的所有商品;

結果就是我們想要的:

注意:

1,這種子查詢語句,沒法“獨立存在(獨立執行)”,而是必須跟主查詢一起使用;

2,其他子查詢,是可以獨立執行的,而且會得到一個執行的結果。

3,該子查詢中的條件,應該設定為跟主查詢的某個欄位有一定的關聯性判斷,通常該判斷就是這兩個表的“本來該有的連線條件”

 

最後一個結論:

如果一個查詢需求,可以使用連線查詢的,也可以使用子查詢得到,則通常推薦使用連線插敘,效率歸更高。

相關文章