連接是關係型數據庫中常用的多表查詢數據的模式,連接可以根據各個表之間的邏輯關係來利用一個表中的數據選擇另外的表中的行實現數據的關聯操作。要在數據庫中完成複雜的查詢,必須將兩個或兩個以上的表連接起來。
連接條件可在 from
或 where
子句中指定。連接條件與where
和having
搜索條件組合,用於控制from
子句引用的數據源中所選定的行。
MySQL
處理連接時,查詢引擎從多種可能的方法中選擇最高效的方法處理連接。儘管不同連接的物理執行可以採用多種不同的優化,但邏輯序列都是通過應用from
、where
和having
子句中的連接條件和搜索條件實現
連接條件中用到的字段雖然不必具有相同的名稱或相同的數據類型,但是如果數據類型不相同,則必須兼容或可進行隱性轉換。
MySQL
顯式定義了連接操作,增強了查詢的可讀性。被顯式定義的與連接有關的關鍵字如下:
(1)inner join:
內連接,結果只包含滿足條件的列。
(2)left outer join:
左外連接,結果包含滿足條件的行及左側表中的全部行。
(3)right outer join:
右外連接,結果包含滿足條件的行及右側表中的全部行。
(4)cross join:
結果只包含兩個表中所有行的組合,指明兩表間的笛卡兒操作。
1.內連接
內連接(inner join
) 查詢是通過比較數據源表間共享列的值,從多個源表檢索符合條件的行的操作。可以使用等號運算符的連接,也可以連接兩個不相等的列中的值。
查詢選修課程號爲c05109的學生的學號、姓名和期末成績。
分析:本例中要求所輸出的列分別在student表和score表中,可以通過studentno列、使用內連接的方式連接兩個表,找出選修課程號爲c05109的行。程序中兩個表存在相同的列studentno,引用時需要標明該列所屬的源表。
mysql> select student.studentno,sname,final
-> from student inner join score
-> on student.studentno= score.studentno
-> where score.courseno = 'c05109';
還有一種方法,就是直接通過where子句的複合條件查詢,可以實現與內連接的同樣結果。代碼如下:
mysql> select student.studentno,sname,final
-> from student,score
-> where student.studentno= score.studentno
-> and score.courseno = 'c05109‘;
2.外連接
外連接(outer join
)包括滿足搜索條件的連接表中的所有行,甚至包括在其他連接表中沒有匹配行的一個表中的行。對於當一個表中的行與其他表中的行不匹配時返回的結果集行,爲解析爲不存在相應行的表的所有結果集列提供null值。
外連接會返回from
子句中提到的至少一個表或視圖中的所有行,只要這些行符合任何where
或having
搜索條件。將檢索通過左外部連接引用的左表中的所有行,以及通過右外部連接引用的右表中的所有行。
外連接是使用outer join
關鍵字將兩個表連接起來。外連接生成的結果集不僅包含符合連接條件的行數據,而且還包括左表(左外連接時的表)、右表(右外連接時的表)中所有的數據行。
(1)左外連接(left outer join
)。
左外連接是指將左表中的所有數據分別與右表中的每條數據進行連接組合,返回的結果除內連接的數據外,還包括左表中不符合條件的數據,並在右表的相應列中添加null
值。
在mysqltest數據庫中利用左外連接方式查詢學生的學號、姓名、平時成績和期末成績。
分析:左外連接方式將會對右表中的行與左表中的行不匹配時,將右表的所有結果集列賦以null 值。
mysql> use mysqltest;
mysql> select student02.studentno,sname,daily,final
-> from student02 left join score1
-> on student02.studentno=score1.studentno;
(2)右外連接(right outer join
)。
右外連接也是外部連接的一種,其中包含 join
子句中最右側表的所有行。如果右側表中的行與左側表中的行不匹配,則將爲結果集中來自左側表的所有列分配 null
值。
利用右外連接方式查詢教師的排課情況。
分析:右外連接方式將會對左表中的行與右表中的行不匹配時,將左表的所有結果集列賦以null 值。
mysql> select teacher.teacherno,tname, major, courseno
-> from teacher right join teach_course
-> on teacher.teacherno = teach_course.teacherno;
3.交叉連接
交叉連接(Cross Join
)是在沒有where
子句的情況下,產生的表的笛卡兒積。兩個表作交叉連接時,結果集大小爲二者行數之積。該種方式在實際過程中用的很少。
顯示student 表和score表的笛卡兒積。
分析:其結果集336行數據,應是student 表數據行數與score錶行數的乘積數。
mysql> select student.studentno,sname,score.*
-> from student cross join score;
4.連接多個表
從理論上說,對於使用select
語句進行連接的表數目沒有上限。但在一條select
語句中連接的表多於10個,那麼數據庫就很可能達不到最優化設計,MySQL
引擎的執行計劃會變得非常繁瑣 。
需要注意的是對於3個以上關係表的連接查詢,一般遵循下列規則:連接n個表至少需要n-1個連接條件,以避免笛卡兒積的出現。爲了縮小結果集,採用多於n-1個連接條件或使用其他條件都是允許的。
查詢18級學生的學號、姓名、課程名、期末成績及學分。
分析:本例要求輸出的各項分別存在於student、 course和 score等3個表中,因此至少需要創建2個連接條件。每16個學時,計爲1學分。
mysql> select student.studentno,sname,cname,final,round(period/16,1)
-> from score join student on student.studentno=score.studentno
-> join course on score.courseno=course.courseno
-> where substring(student.studentno,1,2)='18';
5.合併多個結果集
union
操作符可以將多個select
語句的返回結果組合到一個結果集中。當要檢索的數據在不同的結果集中,並且不能夠利用一個單獨的查詢語句得到時,可以使用union
合併多個結果集。
將兩個或更多查詢的結果合併爲單個結果集,該結果集包含聯合查詢中的所有查詢的全部行。union
運算不同於使用聯接合並兩個表中的列的運算。
使用 union
合併兩個查詢結果集時,所有查詢中的列數和列的順序必須相同且數據類型必須兼容。
union
操作符基本語法格式如下:
select_statement union [all] select_statement
其中,格式中的參數說明如下:
(1)select_statement:
select語句。
(2)union:
指定組合多個結果集並返回爲單個結果集。
(3)All:
將所有行合併到結果中,包括重複的行。如果不指定,將刪除重複的行。
在mysqltest數據庫中利用student表創建student01,將student01和student表的部分查詢結果集合並。
分析:雖然2個表的結構不同,但需要合併的兩個結果集結構和列的數據類型兼容。
mysql> createtable student01 as
-> select studentno,sname,phone from teaching.student;
mysql> select studentno,sname,phone from student01
-> where phone like '%131%'
-> union
-> select studentno,sname,phone from teaching.student
-> where phone like '%132%';