數(shù)據(jù)庫(kù)示例:
學(xué)生信息表student
+-----+------+-----+-----+
| id | name | age | sex |
+-----+------+-----+-----+
| 001 | 張三 | 18 | 男 |
| 002 | 李四 | 20 | 女 |
| 003 | 王五 | 18 | 男 |
+-----+------+-----+-----+
成績(jī)表score
+----+------------+------------+-------+
| id | student_id | subject_id | score |
+----+------------+------------+-------+
| 1 | 001 | 1001 | 80 |
| 2 | 002 | 1002 | 60 |
| 3 | 001 | 1001 | 70 |
| 4 | 002 | 1002 | 60.5 |
+----+------------+------------+-------+
一驶臊、子查詢
一個(gè)內(nèi)層查詢語(yǔ)句(select-from-where)塊可以嵌套在另外一個(gè)外層查詢塊的where子句中棚贾,其中外層查詢也稱為父查詢匿垄,主查詢专执。內(nèi)層查詢也稱子查詢,從查詢验懊。
例如查詢張三的各個(gè)科目的成績(jī):
mysql> SELECT subject_id, score FROM score WHERE student_id = (SELECT id FROM student WHERE name = '張三');
+------------+-------+
| subject_id | score |
+------------+-------+
| 1001 | 80 |
| 1002 | 70 |
+------------+-------+
2 rows in set (0.00 sec)
子查詢可以較方便地對(duì)兩個(gè)或多個(gè)表進(jìn)行查詢吭服,過(guò)程也比較好理解嚷堡。但是當(dāng)查詢的表過(guò)多(超過(guò)3個(gè))時(shí)嵌套的查詢就比較復(fù)雜,會(huì)可讀性艇棕。而且外部的查詢的返回結(jié)果不能包括內(nèi)部查詢的結(jié)果蝌戒。
二串塑、聯(lián)結(jié)查詢
聯(lián)結(jié)查詢可以將表進(jìn)行關(guān)聯(lián),從而顯示出來(lái)自多張表的數(shù)據(jù)北苟。
1. 內(nèi)聯(lián)結(jié)
返回兩個(gè)或者多個(gè)表之間相等關(guān)系的數(shù)據(jù)桩匪,從數(shù)學(xué)關(guān)系來(lái)看,相當(dāng)于求交集粹淋。從左表中取出每一條記錄吸祟,去右表中與所有的記錄進(jìn)行匹配:匹配必須是某個(gè)條件在左表中與右表中相同最終才會(huì)保留結(jié)果,否則不保留桃移。
mysql> SELECT * FROM student INNER JOIN score ON student.id = score.student_id;
+-----+------+-----+-----+----+------------+------------+-------+
| id | name | age | sex | id | student_id | subject_id | score |
+-----+------+-----+-----+----+------------+------------+-------+
| 001 | 張三 | 18 | 男 | 1 | 001 | 1001 | 80 |
| 002 | 李四 | 20 | 女 | 2 | 002 | 1001 | 60 |
| 001 | 張三 | 18 | 男 | 3 | 001 | 1002 | 70 |
| 002 | 李四 | 20 | 女 | 4 | 002 | 1002 | 60.5 |
+-----+------+-----+-----+----+------------+------------+-------+
4 rows in set (0.00 sec)
注:表名太長(zhǎng)時(shí)可以使用別名來(lái)區(qū)分同名字段;可以使用where代替on關(guān)鍵字葛碧,但效率差很多借杰。
2. 外聯(lián)結(jié)
以某張表為主,取出里面的所有記錄,然后每條與另外一張表進(jìn)行連接:不管能不能匹配上條件进泼,最終都會(huì)保留:能匹配蔗衡,正確保留;不能匹配乳绕,其他表的字段都置空NULL绞惦。
- 左外聯(lián)結(jié):以左邊為主表,返回左表中的所有數(shù)據(jù):
mysql> SELECT * FROM student LEFT JOIN score ON student.id = score.student_id;
+-----+------+-----+-----+------+------------+------------+-------+
| id | name | age | sex | id | student_id | subject_id | score |
+-----+------+-----+-----+------+------------+------------+-------+
| 001 | 張三 | 18 | 男 | 1 | 001 | 1001 | 80 |
| 002 | 李四 | 20 | 女 | 2 | 002 | 1001 | 60 |
| 001 | 張三 | 18 | 男 | 3 | 001 | 1002 | 70 |
| 002 | 李四 | 20 | 女 | 4 | 002 | 1002 | 60.5 |
| 003 | 王五 | 18 | 男 | NULL | NULL | NULL | NULL |
+-----+------+-----+-----+------+------------+------------+-------+
5 rows in set (0.00 sec)
- 右外聯(lián)結(jié):以右邊為主表洋措,返回右表中的所有數(shù)據(jù):
mysql> SELECT * FROM student RIGHT JOIN score ON student.id = score.student_id;
+------+------+------+------+----+------------+------------+-------+
| id | name | age | sex | id | student_id | subject_id | score |
+------+------+------+------+----+------------+------------+-------+
| 001 | 張三 | 18 | 男 | 1 | 001 | 1001 | 80 |
| 001 | 張三 | 18 | 男 | 3 | 001 | 1002 | 70 |
| 002 | 李四 | 20 | 女 | 2 | 002 | 1001 | 60 |
| 002 | 李四 | 20 | 女 | 4 | 002 | 1002 | 60.5 |
+------+------+------+------+----+------------+------------+-------+
4 rows in set (0.00 sec)
3. 交叉聯(lián)結(jié)
從一張表中循環(huán)取出每一條記錄济蝉,每條記錄都去另外一張表進(jìn)行匹配:匹配一定保留(沒(méi)有條件匹配),而連接本身字段就會(huì)增加(保留)菠发,最終形成的結(jié)果叫做:笛卡爾積王滤。
SELECT * FROM table1 AS t1 CROSS JOIN table2 AS t2;
4. 自聯(lián)結(jié)
有時(shí)需要在同一張表中進(jìn)行聯(lián)結(jié)條件的匹配或字段比較,可以使用自聯(lián)結(jié)滓鸠。
SELECT * FROM table t1, table t2 WHERE t1.column1=t2.column2;
三雁乡、組合查詢
多數(shù)SQL查詢都只包含從一個(gè)或多個(gè)表中返回?cái)?shù)據(jù)的單條SELECT語(yǔ)句。MySQL也允許執(zhí)行多個(gè)查詢(多條SELECT語(yǔ)句)糜俗,并將結(jié)果作為單個(gè)查詢結(jié)果集返回踱稍。一般在以下兩種情況中使用:
- 在單個(gè)查詢中,從不同表中返回類似結(jié)構(gòu)的數(shù)據(jù)悠抹。
- 對(duì)單個(gè)表執(zhí)行多個(gè)查詢珠月,按照單個(gè)查詢返回?cái)?shù)據(jù)。
SELECT * FROM table1 WHERE condition
UNION
SELECT * FROM table2 WHERE condition;
第一種情況锌钮,例:
mysql> SELECT student_id,score FROM score WHERE score > 65
-> UNION
-> SELECT id,age FROM student WHERE age >= 20;
+------------+-------+
| student_id | score |
+------------+-------+
| 001 | 80 |
| 001 | 70 |
| 002 | 20 |
+------------+-------+
3 rows in set (0.00 sec)
第二種情況桥温,例:
mysql> SELECT * FROM score WHERE score > 65 UNION SELECT * FROM score WHERE id = 4;
+----+------------+------------+-------+
| id | student_id | subject_id | score |
+----+------------+------------+-------+
| 1 | 001 | 1001 | 80 |
| 3 | 001 | 1002 | 70 |
| 4 | 002 | 1002 | 60.5 |
+----+------------+------------+-------+
3 rows in set (0.00 sec)
此種情況下(即情況2),可以用一個(gè)SELECT語(yǔ)句加上WHERE條件來(lái)實(shí)現(xiàn)梁丘。
注:
- UNION中的每個(gè)查詢必須包含相同的列侵浸、表達(dá)式或聚集函數(shù)旺韭。
- UNION中的每個(gè)SELECT語(yǔ)句返回的列類型必須兼容√途酰可以不必完全相同区端,但是可以隱式轉(zhuǎn)換。
- UNION默認(rèn)會(huì)消除重復(fù)的行澳腹,如果要返回所有行:請(qǐng)用UNION ALL织盼。
- 再用UNION查詢時(shí),只能使用一條ORDER BY子句酱塔,它必須出現(xiàn)在最后一條SELECT之后沥邻。