mysql 子查詢與連接表詳情
1、什么是子查詢?
列出訂購(gòu)物品TNT2的所有客戶:
select cust_id from orders where order_num IN (SELECT order_num from orderitems where prod_id = 'TNT2' )
格式化SQL
包含子查詢的SELECT
語(yǔ)句難以閱讀和調(diào)試,特別是它們較為復(fù)雜時(shí)更是如此。如上所示把子查詢分解為多行并且適當(dāng)?shù)剡M(jìn)行縮進(jìn),能極大地簡(jiǎn)化子查詢的使用。
對(duì)于能嵌套的子查詢的數(shù)目沒有限制,不過(guò)在實(shí)際使用時(shí)由于性能的限制,不能嵌套太多的子查詢。
注:
列必須匹配 在
WHERE
子句中使用子查詢(如這里所示),應(yīng)該保證SELECT
語(yǔ)句具有與WHERE
子句中相同數(shù)目的列。通常,
子查詢將返回單個(gè)列并且與單個(gè)列匹配,但如果需要也可以使用多個(gè)列。
除了子查詢可以放在where
中,還可以放到select
中去。
假如需要顯示customers
表中每個(gè)客戶的訂單總數(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
mysql
的運(yùn)行過(guò)程是先執(zhí)行了customers
中查出來(lái)了cust_name
,cust_state
,cust_id
,然后執(zhí)行5次子查詢,查出來(lái)了結(jié)果。
逐漸增加子查詢來(lái)建立查詢 用子查詢測(cè)試和調(diào)試查詢很有技巧性,特別是在這些語(yǔ)句的復(fù)雜性不斷增加的情況下更是如此。用子查詢建立(和測(cè)試)查詢的最可靠的方法是逐漸進(jìn)行,這與MySQL處理它們的方法非常相同。首先,建立和測(cè)試最內(nèi)層的查詢。然后,用硬編碼數(shù)據(jù)建立和測(cè)試外層查詢,并且僅在確認(rèn)它正常后才嵌入子查詢。這時(shí),再次測(cè)試它。對(duì)于要增加的每個(gè)查詢,重復(fù)這些步驟。這樣做僅給構(gòu)造查詢?cè)黾恿艘稽c(diǎn)點(diǎn)時(shí)間,但節(jié)省了以后(找出查詢?yōu)槭裁床徽#┑拇罅繒r(shí)間,并且極大地提高了查詢一開始就正常工作的可能性
下面介紹一下聯(lián)結(jié):
SELECT vend_name,prod_name,prod_price FROM vendors,products WHERE vendors.vend_id=products.vend_id ORDER BY vend_name, prod_name
注:
完全限定列名 在引用的列可能出現(xiàn)二義性時(shí),必須使用完全限定列名(用一個(gè)點(diǎn)分隔的表名和列名)。如果引用一個(gè)沒有用表名限制的具有二義性的列名,MySQL將返回錯(cuò)誤。
這里使用where 語(yǔ)句進(jìn)行聯(lián)接的作用:
利用WHERE子句建立聯(lián)結(jié)關(guān)系似乎有點(diǎn)奇怪,但實(shí)際上,有一個(gè)很充分的理由。請(qǐng)記住,在一條SELECT語(yǔ)句中聯(lián)結(jié)幾個(gè)表時(shí),相應(yīng)的關(guān)系是在運(yùn)行中構(gòu)造的。在數(shù)據(jù)庫(kù)表的定義中不存在能指示MySQL如何對(duì)表進(jìn)行聯(lián)結(jié)的東西。你必須自己做這件事情。在聯(lián)結(jié)兩個(gè)表時(shí),你實(shí)際上做的是將第一個(gè)表中的每一行與第二個(gè)表中的每一行配對(duì)。WHERE子句作為過(guò)濾條件,它只包含那些匹配給定條件(這里是聯(lián)結(jié)條件)的行。沒有WHERE子句,第一個(gè)表中的每個(gè)行將與第二個(gè)表中的每個(gè)行配對(duì),而不管它們邏輯上是否可以配在一起。
注:
笛卡兒積(
cartesian product
) 由沒有聯(lián)結(jié)條件的表關(guān)系返回的結(jié)果為笛卡兒積。檢索出的行的數(shù)目將是第一個(gè)表中的行數(shù)乘以第二個(gè)表中的行數(shù)。目前為止所用的聯(lián)結(jié)稱為等值聯(lián)結(jié)(equijoin
),它基于兩個(gè)表之間的相等測(cè)試。這種聯(lián)結(jié)也稱為內(nèi)部聯(lián)結(jié)。其實(shí),對(duì)于這種聯(lián)結(jié)可以使用稍微不同的語(yǔ)法來(lái)明確指定聯(lián)結(jié)的類型。
下面的SELECT語(yǔ)句返回與前面例子完全相同的數(shù)據(jù):
SELECT vend_name,prod_name,prod_price FROM vendors INNER JOIN products on vendors.vend_id = products.vend_id ORDER BY vend_name, prod_name
使用哪種語(yǔ)法 ANSI SQL
規(guī)范首選INNER JOIN
語(yǔ)法。此外,盡管使用WHERE
子句定義聯(lián)結(jié)的確比較簡(jiǎn)單,但是使用明確的
聯(lián)結(jié)語(yǔ)法能夠確保不會(huì)忘記聯(lián)結(jié)條件,有時(shí)候這樣做也能影響性能。
性能考慮 MySQL
在運(yùn)行時(shí)關(guān)聯(lián)指定的每個(gè)表以處理聯(lián)結(jié)。這種處理可能是非常耗費(fèi)資源的,因此應(yīng)該仔細(xì),不要聯(lián)結(jié)
不必要的表。聯(lián)結(jié)的表越多,性能下降越厲害。
多做實(shí)驗(yàn) 正如所見,為執(zhí)行任一給定的SQL操作,一般存在不止一種方法。很少有絕對(duì)正確或絕對(duì)錯(cuò)誤的方法。性能可能
會(huì)受操作類型、表中數(shù)據(jù)量、是否存在索引或鍵以及其他一些條件的影響。因此,有必要對(duì)不同的選擇機(jī)制進(jìn)行實(shí)驗(yàn),以找
出最適合具體情況的方法。我們同樣可以使用多張表的聯(lián)接,但是有一個(gè)問題,因?yàn)楸砻鄠€(gè)地方使用,故而表名很長(zhǎng),那么可以使用表的別名。
如:
下面介紹一下幾種特殊的連接。
2、自聯(lián)接
假如你發(fā)現(xiàn)某物品(其ID
為DTNTR
)存在問題,因此想知道生產(chǎn)該物品的供應(yīng)商生產(chǎn)的其他物品是否也存在這些問題。此查詢要求首先找到生產(chǎn)ID
為DTNTR
的物品的供應(yīng)商,然后找出這個(gè)供應(yīng)商生產(chǎn)的其他物品。
下面是解決此問題的一種方法:
你可能使用子查詢,這樣做:
select prod_id,prod_name from products where vend_id = (SELECT vend_id from products WHERE prod_id ='DTNTR')
同樣可以使用自聯(lián)接。
select t1.prod_id,t2.prod_name from products t1, products t2 where t1.vend_id = t2.vend_id and t1.prod_id='DTNTR'
用自聯(lián)結(jié)而不用子查詢 自聯(lián)結(jié)通常作為外部語(yǔ)句用來(lái)替代從相同表中檢索數(shù)據(jù)時(shí)使用的子查詢語(yǔ)句。雖然最終的結(jié)果是
相同的,但有時(shí)候處理聯(lián)結(jié)遠(yuǎn)比處理子查詢快得多。應(yīng)該試一下兩種方法,以確定哪一種的性能更好。
3、自然聯(lián)接
無(wú)論何時(shí)對(duì)表進(jìn)行聯(lián)結(jié),應(yīng)該至少有一個(gè)列出現(xiàn)在不止一個(gè)表中(被聯(lián)結(jié)的列)。標(biāo)準(zhǔn)的聯(lián)結(jié)(前一章中介紹的內(nèi)部聯(lián)結(jié))返回所有數(shù)據(jù),甚至相同的列多次出現(xiàn)。自然聯(lián)結(jié)排除多次出現(xiàn),使每個(gè)列只返回一次。
怎樣完成這項(xiàng)工作呢?答案是,系統(tǒng)不完成這項(xiàng)工作,由你自己完成它。自然聯(lián)結(jié)是這樣一種聯(lián)結(jié),其中你只能選擇那些唯一的列。這一般是通過(guò)對(duì)表使用通配符(SELECT *
)對(duì)所有其他表的列使用明確的子集來(lái)完成的。
4、外部聯(lián)結(jié)
許多聯(lián)結(jié)將一個(gè)表中的行與另一個(gè)表中的行相關(guān)聯(lián)。但有時(shí)候會(huì)需要包含沒有關(guān)聯(lián)行的那些行。例如,可能需要使用聯(lián)結(jié)來(lái)完成以下工作:
比如:對(duì)每個(gè)客戶下了多少訂單進(jìn)行計(jì)數(shù),包括那些至今尚未下訂單的客戶;
SELECT customers.cust_id,order_num from customers LEFT OUTER JOIN orders on customers.cust_id = orders.cust_id
這條SELECT
語(yǔ)句使用了關(guān)鍵字OUTER JOIN
來(lái)指定聯(lián)結(jié)的類型(而不是在WHERE
子句中指定)。但是,與內(nèi)部聯(lián)結(jié)關(guān)聯(lián)兩個(gè)表中的行不同的是,外部聯(lián)結(jié)還包括沒有關(guān)聯(lián)行的行。在使用OUTER JOIN
語(yǔ)法時(shí),必須使用RIGHT
或LEFT
關(guān)鍵字
指定包括其所有行的表(RIGHT
指出的是OUTER JOIN
右邊的表,而LEFT指出的是OUTER JOIN
左邊的表)。
使用帶聚集函數(shù)的聯(lián)結(jié):
要檢索所有客戶及每個(gè)客戶所下的訂單數(shù):
SELECT customers.cust_id, COUNT(order_num) as num from customers LEFT OUTER JOIN orders on customers.cust_id = orders.cust_id GROUP BY cust_id
注意點(diǎn):
1.注意所使用的聯(lián)結(jié)類型。一般我們使用內(nèi)部聯(lián)結(jié),但使用外部聯(lián)結(jié)也是有效的。
2.保證使用正確的聯(lián)結(jié)條件,否則將返回不正確的數(shù)據(jù)。
3.應(yīng)該總是提供聯(lián)結(jié)條件,否則會(huì)得出笛卡兒積。
4.在一個(gè)聯(lián)結(jié)中可以包含多個(gè)表,甚至對(duì)于每個(gè)聯(lián)結(jié)可以采用不同的聯(lián)結(jié)類型。雖然這樣做是合法的,一般也很有用,但應(yīng)該在一起測(cè)試它們前,分別測(cè)試每個(gè)聯(lián)結(jié)。這將使故障排除更為簡(jiǎn)單。
到此這篇關(guān)于mysql 子查詢與連接表詳情的文章就介紹到這了,更多相關(guān)mysql 子查詢與連接表內(nèi)容請(qǐng)搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!
版權(quán)聲明:本站文章來(lái)源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來(lái)源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來(lái)源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來(lái),僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。