mysql 子查询
接上篇文章,從這節(jié)起:MySQL 5.7?13.2.10.5?Row Subqueries
?
五、行子查詢(ROW Subqueries)
標(biāo)量子查詢返回單個(gè)值,列子查詢返回一個(gè)列的多個(gè)值。而行子查詢是子查詢變體,它返回單個(gè)行,因此可以返回多個(gè)列值。
可用于行子查詢比較的操作符如下:
= > < >= <= <> != <=>以下是兩個(gè)示例:
SELECT * FROM t1WHERE (col1,col2) = (SELECT col3, col4 FROM t2 WHERE id = 10);SELECT * FROM t1WHERE ROW(col1,col2) = (SELECT col3, col4 FROM t2 WHERE id = 10);對(duì)于這兩個(gè)查詢,如果t2表中有一個(gè)id=10的行(僅有一個(gè)),則子查詢返回這單個(gè)行。如果這行數(shù)據(jù)中的col3、col4兩個(gè)列的列值與t1表中的任何行的col1、col2相等,則WHERE表達(dá)式返回TRUE。兩個(gè)查詢都t1表中的這些行。
如果t2行col3和col4值不等于任何t1行的col1和col2值,則WHERE表達(dá)式為FALSE且查詢返回空結(jié)果集。
如果子查詢不生成行(空的結(jié)果集),則表達(dá)式是未知的(即NULL)。如果子查詢產(chǎn)生多行,則會(huì)發(fā)生錯(cuò)誤,因?yàn)橐粋€(gè)行子查詢最多只能返回一行。
有關(guān)每個(gè)運(yùn)算符如何進(jìn)行行比較的信息,see Section?12.3.2, “Comparison Functions and Operators”.
表達(dá)式(1,2)和ROW(1,2)有時(shí)被稱為行構(gòu)造器。兩者是等價(jià)的。行構(gòu)造函數(shù)和行子查詢返回的行必須包含相同數(shù)量的值。
行構(gòu)造函數(shù)用于與返回兩列或更多列的子查詢進(jìn)行比較(只返回一行數(shù)據(jù))。當(dāng)子查詢返回單個(gè)列時(shí),這被視為標(biāo)量值而不是行,因此行構(gòu)造函數(shù)不能與不返回至少兩列的子查詢一起使用。
因此以下查詢會(huì)失敗并出現(xiàn)語法錯(cuò)誤:
SELECT * FROM t1 WHERE ROW(1) = (SELECT column1 FROM t2)行構(gòu)造函數(shù)在其他上下文中是合法的。例如,以下兩個(gè)語句在語義上是等效的(并且由優(yōu)化器以相同的方式處理):
SELECT * FROM t1 WHERE (column1,column2) = (1,1); SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;以下查詢回答請(qǐng)求,“查找表t1中也存在于表t2中的所有行”
SELECT column1,column2,column3FROM t1WHERE (column1,column2,column3) IN(SELECT column1,column2,column3 FROM t2);關(guān)于優(yōu)化器和行構(gòu)造器的更多信息,see Section?8.2.1.19, “Row Constructor Expression Optimization”。
?
六、具有EXISTS或NOT EXISTS的子查詢
If a subquery returns any rows at all, EXISTS subquery is TRUE, and NOT EXISTS subquery is FALSE.(如果一個(gè)子查詢返回任何行,那么“EXISTS subquery 會(huì)返回TRUE,NOT EXISTS subquery返回FALSE”)
如下:
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);傳統(tǒng)上,EXISTS子查詢以SELECT *開頭,但它可以從SELECT 5或SELECT column1開始,或者任何東西。因?yàn)镸ySQL忽略了這樣一個(gè)子查詢中的SELECT列表,所以沒有區(qū)別。
之前的例子中,如果t2表中有任何數(shù)據(jù)行,哪怕是全為NULL值的一行數(shù)據(jù),那么EXISTS條件判斷也會(huì)為TRUE。這實(shí)際上是一個(gè)不太可能出現(xiàn)的例子,因?yàn)閇NOT] EXISTS子查詢幾乎總是包含相關(guān)性。下面列出了更現(xiàn)實(shí)的例子:
1、一個(gè)或多個(gè)城市有哪種類型的商店(找出在stores表和cities_stores都存在的
store_type)
2、所有的城市都沒有的商店類型是哪種?(找出在stores表和cities_stores都不存在的
store_type)
3、所有城市都有的商店類型是哪種?
SELECT DISTINCT store_type FROM stores s1WHERE NOT EXISTS (SELECT * FROM cities WHERE NOT EXISTS (SELECT * FROM cities_storesWHERE cities_stores.city = cities.cityAND cities_stores.store_type = stores.store_type));最后一個(gè)示例是雙嵌套的NOT EXISTS查詢。也就是說,它在NOT EXISTS子句中還有一個(gè)NOT EXISTS子句。在形式上,它回答了這樣一個(gè)問題——一個(gè)城市是否存在在Stores表中不存在的商店?更簡(jiǎn)單的說法是:嵌套的NOT EXISTS回答了這樣的問題——“is x TRUE for all y?”
?
七、相關(guān)子查詢(Correlated Subqueries)
相關(guān)子查詢是這樣一個(gè)子查詢——在子查詢中引用外接查詢中的表。
如下所示:
SELECT * FROM t1WHERE column1 = ANY (SELECT column1 FROM t2WHERE t2.column2 = t1.column2);請(qǐng)注意,子查詢包含對(duì)t1表中列的引用,即使子查詢的FROM子句未提及表t1。MySQL會(huì)在子查詢外部查找t1。
假設(shè)t1表有這樣一個(gè)行:column1=5,column2=6;
同時(shí),t2表包含這樣一個(gè)行:column1=5,column2=7;
此時(shí),WHERE表達(dá)式“WHERE column1 = ANY(SELECT column1 FROM t2)”會(huì)返回TRUE。但在上面的例子中,子查詢中的WHERE子句為FALSE,所以整個(gè)子句返回空集,而外部的WHERE表達(dá)式總為FALSE。
?
范圍規(guī)則:MySQL會(huì)從內(nèi)到外對(duì)語句進(jìn)行評(píng)估。
SELECT column1 FROM t1 AS xWHERE x.column1 = (SELECT column1 FROM t2 AS xWHERE x.column1 = (SELECT column1 FROM t3WHERE x.column2 = t3.column1));在這個(gè)語句中,x.column2必須是表t2中的一列,因?yàn)镾ELECT column1 FROM t2 AS x ...重命名t2。它不是表t1中的列,因?yàn)镾ELECT column1 FROM t1 ...是一個(gè)更遠(yuǎn)的外部查詢。
對(duì)于HAVING或ORDER BY子句中的子查詢,MySQL還會(huì)在外部的SELECT列表中查找列名。
在某些情況下,相關(guān)子查詢會(huì)被優(yōu)化掉。例如:
val IN (SELECT key_val FROM tbl_name WHERE correlated_condition)否則,它們效率低下并且可能很慢。將查詢重寫為連接可能會(huì)提高性能。
相關(guān)子查詢中的聚合函數(shù)可能包含外部引用,前提是該函數(shù)只包含外部引用,并且該函數(shù)不包含在另一個(gè)函數(shù)或表達(dá)式中。
總結(jié)
- 上一篇: 详细讲述MySQL中的子查询操作
- 下一篇: MySQL学习(四、子查询)