mysql的复杂查询_mysql复杂查询
所謂復(fù)雜查詢,指涉及多個(gè)表、具有嵌套等復(fù)雜結(jié)構(gòu)的查詢。這里簡(jiǎn)要介紹典型的幾種復(fù)雜查詢格式。
一、連接查詢
連接是區(qū)別關(guān)系與非關(guān)系系統(tǒng)的最重要的標(biāo)志。通過連接運(yùn)算符可以實(shí)現(xiàn)多個(gè)表查詢。連接查詢主要包括內(nèi)連接、外連接等。
假設(shè)有Student和Grade兩個(gè)表如下:
+-----+--------+-------+ +-----+------------+--------+
| sID | sName | sDept | | gID | gCourse | gScore |
+-----+--------+-------+ +-----+------------+--------+
| 1 | Paul | CS | | 1 | Math | 87 |
| 2 | Oliver | MS | | 2 | English | 95 |
| 3 | Jack | SE | | 3 | Physics | 76 |
| 4 | Robin | CS | | 7 | Philosophy | 76 |
+-----+--------+-------+ +-----+------------+--------+
1.1 內(nèi)連接
內(nèi)連接(INNER JOIN)使用比較運(yùn)算符進(jìn)行表間列數(shù)據(jù)的比較操作,并列出這些表中與連接條件相匹配的數(shù)據(jù)行,組合成新的記錄。
當(dāng)比較操作符是=時(shí),稱為等值連接:
SELECT * FROM Student INNER JOIN Grade ON Student.sID = Grade.gID;
等價(jià)于
SELECT * FROM Student,Grade WHERE Student.sID = Grade.gID;
結(jié)果如下:
+-----+--------+-------+-----+---------+--------+
| sID | sName | sDept | gID | gCourse | gScore |
+-----+--------+-------+-----+---------+--------+
| 1 | Paul | CS | 1 | Math | 87 |
| 2 | Oliver | MS | 2 | English | 95 |
| 3 | Jack | SE | 3 | Physics | 76 |
+-----+--------+-------+-----+---------+--------+
可以看出,在內(nèi)連接查詢中,只有滿足條件的記錄才能出現(xiàn)在結(jié)果關(guān)系中。
1.2 外連接
與內(nèi)連接不同的是,外連接返回的查詢結(jié)果集中不僅包含符合連接條件的行,而且還包括左表(左連接)、右表(右連接)或兩個(gè)表(全外連接)中的所有數(shù)據(jù)行。
1.2.1 左連接
LEFT JOIN(左連接),即LEFT OUTER JOIN,返回左表的全部記錄,即使右表中沒有對(duì)應(yīng)匹配記錄。
SELECT * FROM Student LEFT JOIN Grade ON Student.sID = Grade.gID;
結(jié)果如下:
+-----+--------+-------+------+---------+--------+
| sID | sName | sDept | gID | gCourse | gScore |
+-----+--------+-------+------+---------+--------+
| 1 | Paul | CS | 1 | Math | 87 |
| 2 | Oliver | MS | 2 | English | 95 |
| 3 | Jack | SE | 3 | Physics | 76 |
| 4 | Robin | CS | NULL | NULL | NULL |
+-----+--------+-------+------+---------+--------+
1.2.2 右連接
RIGHT JOIN(右連接),即RIGHT OUTER JOIN,返回右表的全部記錄,即使左表中沒有對(duì)應(yīng)匹配記錄。
SELECT * FROM Student RIGHT JOIN Grade ON Student.sID = Grade.gID;
結(jié)果如下:
+------+--------+-------+-----+------------+--------+
| sID | sName | sDept | gID | gCourse | gScore |
+------+--------+-------+-----+------------+--------+
| 1 | Paul | CS | 1 | Math | 87 |
| 2 | Oliver | MS | 2 | English | 95 |
| 3 | Jack | SE | 3 | Physics | 76 |
| NULL | NULL | NULL | 7 | Philosophy | 76 |
+------+--------+-------+-----+------------+--------+
1.2.3 全連接
FULL JOIN(全連接),即FULL OUTER JOIN,返回左表、右表的全部記錄,即使沒有對(duì)應(yīng)的匹配記錄。
**注意:**MySQL不支持FULL JOIN,不過可以通過UNION關(guān)鍵字來合并 LEFT JOIN 與 RIGHT JOIN來模擬。
SELECT * FROM Student LEFT JOIN Grade ON Student.sID = Grade.gID
UNION
SELECT * FROM Student RIGHT JOIN Grade ON Student.sID = Grade.gID
結(jié)果如下:
+------+--------+-------+------+------------+--------+
| sID | sName | sDept | gID | gCourse | gScore |
+------+--------+-------+------+------------+--------+
| 1 | Paul | CS | 1 | Math | 87 |
| 2 | Oliver | MS | 2 | English | 95 |
| 3 | Jack | SE | 3 | Physics | 76 |
| 4 | Robin | CS | NULL | NULL | NULL |
| NULL | NULL | NULL | 7 | Philosophy | 76 |
+------+--------+-------+------+------------+--------+
另外,如果在一個(gè)連接查詢中涉及到的兩個(gè)表是同一個(gè)表,這種查詢稱為自連接查詢。為了防止產(chǎn)生二義性,自連接查詢中通常對(duì)表使用別名。
二、子查詢
子查詢是指一個(gè)查詢語句嵌套在另一個(gè)查詢語句內(nèi)部的查詢。在 SELECT 子句中先計(jì)算子查詢,子查詢結(jié)果作為外層另一個(gè)查詢的過濾條件。
子查詢中常用的操作符有ANY、SOME、ALL、EXISTS、IN,也可以使用比較運(yùn)算符。子查詢可以添加到 SELECT、UPDATE 和 DELETE 語句中,而且可以進(jìn)行多層嵌套。
2.1 在條件表達(dá)式中產(chǎn)生標(biāo)量的子查詢
SELECT *
FROM score
WHERE id = (SELECT event_id
FROM event
WHERE date='2015-07-01'
AND type='Q');
所謂標(biāo)量,就是單個(gè)屬性的一個(gè)原子值。當(dāng)子查詢出現(xiàn)在 WHERE 子句中的比較運(yùn)算符(= ,>, >= ,< , <= ,<>)的右邊,其輸出結(jié)果應(yīng)該只有一個(gè)才對(duì)。很容易理解,如果返回多條結(jié)果,就無法進(jìn)行比較,系統(tǒng)就會(huì)報(bào)錯(cuò)。
又如:
SELECT * FROM teacher WHERE birth = MIN(birth); /*錯(cuò)誤*/
這個(gè)查詢是錯(cuò)的!因?yàn)镸ySQL不允許在子句里面使用統(tǒng)計(jì)函數(shù),所以改用子查詢:
SELECT *
FROM teacher
WHERE birth = (SELECT MIN(birth)
FROM teacher);
2.2 在條件表達(dá)式中產(chǎn)生集合的子查詢
如果子查詢的輸出是一個(gè)結(jié)果集合,可以通過 ANY、ALL、IN 進(jìn)行比較。
2.2.1 ANY與SOME
ANY和SOME關(guān)鍵字是同義詞,表示滿足其中任一條件。它們?cè)试S創(chuàng)建一個(gè)表達(dá)式對(duì)子查詢的返回結(jié)果集進(jìn)行比較:
SELECT num1
FROM t1
WHERE num1 > ANY(SELECT num2
FROM t2);
上面的子查詢返回 t2 的 num2 列,然后將 t1 中的 num1 值與之進(jìn)行比較,只要大于 num2 的任何一個(gè)值,即為符合查詢條件的結(jié)果。
等價(jià)于:
SELECT num1
FROM t1
WHERE num1 > SOME(SELECT num2
FROM t2);
2.2.2 ALL
與ANY/SOME不同,使用ALL時(shí)需要同時(shí)滿足所有內(nèi)層查詢的條件。
SELECT num1
FROM t1
WHERE num1 > ALL(SELECT num2
FROM t2);
上面的子查詢還是返回 t2 的 num2 列,然后將 t1 中的 num1 值與之進(jìn)行比較。但是只有大于所有 num2 值的 num1 才是符合查詢條件的結(jié)果。
2.2.3 IN
IN關(guān)鍵字后接一個(gè)子查詢,若在子查詢結(jié)果集中,返回true,否則返回false。與之相對(duì)的是NOT IN。
SELECT num1
FROM t1
WHERE num1 IN (SELECT num2
FROM t2);
2.3 在條件表達(dá)式中測(cè)試空/非空的子查詢
EXISTS關(guān)鍵字后接一個(gè)任意的子查詢,系統(tǒng)對(duì)子查詢進(jìn)行運(yùn)算以判斷它是否返回行。
若至少返回一行,那么 EXISTS 的結(jié)果為 true,此時(shí)外層查詢語句將進(jìn)行查詢;
若沒有返回任何行,那么 EXISTS 的結(jié)果為 false,此時(shí)外層語句將不進(jìn)行查詢。
SELECT sName
FROM Student
WHERE EXISTS (SELECT *
FROM Grade
WHERE gScore < 60);
EXISTS和NOT EXISTS的結(jié)果只取決于是否會(huì)返回行,而不取決于這些行的內(nèi)容。
2.4 關(guān)聯(lián)子查詢
一般的子查詢只計(jì)算一次,其結(jié)果用于外層查詢。但關(guān)聯(lián)子查詢需要計(jì)算多次。
子查詢中使用了主查詢中的某些字段,主查詢每掃描一行都要執(zhí)行一次子查詢,這種子查詢稱為關(guān)聯(lián)子查詢(Correlated Subquery)。
SELECT sName
FROM Student
WHERE '450' NOT IN (SELECT courseID
FROM Course
WHERE sID = Student.sID);
上面的子查詢中使用了 Student 表的 sID 字段。對(duì)于 Student 表中每一個(gè) sID 都會(huì)執(zhí)行一次子查詢。
2.5 FROM子句中的子查詢
子查詢可以用括號(hào)括起來作為一個(gè)關(guān)系,從而出現(xiàn)在 FROM 列表中。由于子查詢的結(jié)果關(guān)系沒有正式的名字,故必須給它取一個(gè)別名。
SELECT *
FROM Grade,
(SELECT * FROM Student WHERE sDept='CS')x
WHERE x.sID=Grade.gID;
x 就是子查詢的結(jié)果關(guān)系的別名。
三、合并查詢結(jié)果
利用UNION或UNION ALL關(guān)鍵字,可以將多個(gè) SELECT 語句的結(jié)果組合成單個(gè)結(jié)果集。合并時(shí),兩個(gè)表對(duì)應(yīng)的列數(shù)和數(shù)據(jù)類型必須相同。
UNION:合并查詢結(jié)果時(shí),刪除重復(fù)的記錄,返回的行都是唯一的。
UNION ALL:合并查詢結(jié)果時(shí),不刪除重復(fù)行。
3.1 UNION ALL
SELECT * FROM Student
UNION ALL
SELECT * FROM Student;
結(jié)果如下:
+-----+--------+-------+
| sID | sName | sDept |
+-----+--------+-------+
| 1 | Paul | CS |
| 2 | Oliver | MS |
| 3 | Jack | SE |
| 4 | Robin | CS |
| 1 | Paul | CS |
| 2 | Oliver | MS |
| 3 | Jack | SE |
| 4 | Robin | CS |
+-----+--------+-------+
3.2 UNION
SELECT * FROM Student
UNION
SELECT * FROM Student;
結(jié)果如下:
+-----+--------+-------+
| sID | sName | sDept |
+-----+--------+-------+
| 1 | Paul | CS |
| 2 | Oliver | MS |
| 3 | Jack | SE |
| 4 | Robin | CS |
+-----+--------+-------+
總結(jié)
以上是生活随笔為你收集整理的mysql的复杂查询_mysql复杂查询的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: import 别名_Python基础找茬
- 下一篇: mysql signed 长度_浅谈my