JOIN用於多張表的關聯查詢,如SELECT子句(SELECT A.a,A.b,B.a,B.d)中既有表A的字段,同時還有B表的字段,此時使用單獨使用FROM A或FROM B已經解決不了問題了,使用JOIN來關聯表A和表B便可解決問題,即FROM A,B或A JOIN B,這種方式獲得的結果實際上是表A與表B的笛卡爾積,即若是A是M1行,N1列的表,B是M2行,N2列的表,A JOIN B的結果是(M1*M2)行,(N1+N2)列的結果集。JOIN能夠是等值鏈接(A JOIN B ON (A.a=B.c)),也能夠是非等值鏈接(即大於,小於等,如A JOIN B ON(A.a > B.c)),也能夠不使用任何條件JOIN,即笛卡爾積,可是非等值鏈接和笛卡爾積實際意義不大,特別是還存在性能問題。性能
測試表:測試
create table tbl_course( course_id bigint not null primary key, course_name varchar(12) not null ); create table tbl_student( stu_id bigint not null, stu_name varchar(12), constraint pk_tbl_student_stu_id primary key(stu_id) ); create table tbl_student_course( stu_id bigint not null, course_id bigint not null, constraint pk_tbl_student_course_stu_id_course_id primary key(stu_id,course_id), constraint fk_tbl_student_course_stu_id foreign key(stu_id) references tbl_student(stu_id) , constraint fk_tbl_student_course_course_id foreign key(course_id) references tbl_course(course_id) );
test=# insert into tbl_course values(1,'高等數學'),(2,'大學英語'),(3,'大學物理'),(4,'電影欣賞'); INSERT 0 4 test=# insert into tbl_student values(1,'張三'),(2,'李四'),(3,'王五'),(4,'麻子'); INSERT 0 4 test=# insert into tbl_student_course values (1,2),(1,4),(2,4),(3,4); INSERT 0 4
示例.笛卡爾積確實沒什麼實際意義,測試表中其實只有4個選課數據。spa
test=# select * from tbl_course ,tbl_student,tbl_student_course; course_id | course_name | stu_id | stu_name | stu_id | course_id -----------+-------------+--------+----------+--------+----------- 1 | 高等數學 | 1 | 張三 | 1 | 2 1 | 高等數學 | 1 | 張三 | 1 | 4 1 | 高等數學 | 1 | 張三 | 2 | 4 1 | 高等數學 | 1 | 張三 | 3 | 4 1 | 高等數學 | 2 | 李四 | 1 | 2 1 | 高等數學 | 2 | 李四 | 1 | 4 1 | 高等數學 | 2 | 李四 | 2 | 4 1 | 高等數學 | 2 | 李四 | 3 | 4 1 | 高等數學 | 3 | 王五 | 1 | 2 1 | 高等數學 | 3 | 王五 | 1 | 4 1 | 高等數學 | 3 | 王五 | 2 | 4 1 | 高等數學 | 3 | 王五 | 3 | 4 1 | 高等數學 | 4 | 麻子 | 1 | 2 1 | 高等數學 | 4 | 麻子 | 1 | 4 1 | 高等數學 | 4 | 麻子 | 2 | 4 1 | 高等數學 | 4 | 麻子 | 3 | 4 2 | 大學英語 | 1 | 張三 | 1 | 2 2 | 大學英語 | 1 | 張三 | 1 | 4 2 | 大學英語 | 1 | 張三 | 2 | 4 2 | 大學英語 | 1 | 張三 | 3 | 4 2 | 大學英語 | 2 | 李四 | 1 | 2 2 | 大學英語 | 2 | 李四 | 1 | 4 2 | 大學英語 | 2 | 李四 | 2 | 4 2 | 大學英語 | 2 | 李四 | 3 | 4 2 | 大學英語 | 3 | 王五 | 1 | 2 2 | 大學英語 | 3 | 王五 | 1 | 4 2 | 大學英語 | 3 | 王五 | 2 | 4 2 | 大學英語 | 3 | 王五 | 3 | 4 2 | 大學英語 | 4 | 麻子 | 1 | 2 2 | 大學英語 | 4 | 麻子 | 1 | 4 2 | 大學英語 | 4 | 麻子 | 2 | 4 2 | 大學英語 | 4 | 麻子 | 3 | 4 3 | 大學物理 | 1 | 張三 | 1 | 2 3 | 大學物理 | 1 | 張三 | 1 | 4 3 | 大學物理 | 1 | 張三 | 2 | 4 3 | 大學物理 | 1 | 張三 | 3 | 4 3 | 大學物理 | 2 | 李四 | 1 | 2 3 | 大學物理 | 2 | 李四 | 1 | 4 3 | 大學物理 | 2 | 李四 | 2 | 4 3 | 大學物理 | 2 | 李四 | 3 | 4 3 | 大學物理 | 3 | 王五 | 1 | 2 3 | 大學物理 | 3 | 王五 | 1 | 4 3 | 大學物理 | 3 | 王五 | 2 | 4 3 | 大學物理 | 3 | 王五 | 3 | 4 3 | 大學物理 | 4 | 麻子 | 1 | 2 3 | 大學物理 | 4 | 麻子 | 1 | 4 3 | 大學物理 | 4 | 麻子 | 2 | 4 3 | 大學物理 | 4 | 麻子 | 3 | 4 4 | 電影欣賞 | 1 | 張三 | 1 | 2 4 | 電影欣賞 | 1 | 張三 | 1 | 4 4 | 電影欣賞 | 1 | 張三 | 2 | 4 4 | 電影欣賞 | 1 | 張三 | 3 | 4 4 | 電影欣賞 | 2 | 李四 | 1 | 2 4 | 電影欣賞 | 2 | 李四 | 1 | 4 4 | 電影欣賞 | 2 | 李四 | 2 | 4 4 | 電影欣賞 | 2 | 李四 | 3 | 4 4 | 電影欣賞 | 3 | 王五 | 1 | 2 4 | 電影欣賞 | 3 | 王五 | 1 | 4 4 | 電影欣賞 | 3 | 王五 | 2 | 4 4 | 電影欣賞 | 3 | 王五 | 3 | 4 4 | 電影欣賞 | 4 | 麻子 | 1 | 2 4 | 電影欣賞 | 4 | 麻子 | 1 | 4 4 | 電影欣賞 | 4 | 麻子 | 2 | 4 4 | 電影欣賞 | 4 | 麻子 | 3 | 4 (64 rows)
JOIN鏈接分爲內鏈接和外鏈接,而外鏈接又分爲左外鏈接,右外鏈接,全外鏈接。3d
INNER JOIN,其中INNER能夠省略。code
語法:blog
A INNER JOIN B ON (A.a = B.b)get
若是ON條件中兩張表的字段名稱相同,還能夠簡單一點數學
A INNER JOIN B USING(a = b)it
內鏈接的結果以下圖中紅色部分io
示例:查詢選課狀況
test=# select * from tbl_student_course join tbl_student using(stu_id) join tbl_course using(course_id); course_id | stu_id | stu_name | course_name -----------+--------+----------+------------- 2 | 1 | 張三 | 大學英語 4 | 1 | 張三 | 電影欣賞 4 | 2 | 李四 | 電影欣賞 4 | 3 | 王五 | 電影欣賞 (4 rows)
左外鏈接實際上是一個內鏈接而後加上左表獨有的數據行,結果集中右表的字段自動補充NULL。
LEFT OUTTER JOIN ,其中OUTTER能夠省略。
語法:
A LEFT JOIN B ON (A.a=B.b)
A LEFT JOIN B USING(a)
左外鏈接的結果以下圖紅色部分
示例:查詢全部學生的選課信息,包括沒選課的學生
test=# select * from tbl_student left join tbl_student_course using(stu_id) left join tbl_course using(course_id); course_id | stu_id | stu_name | course_name -----------+--------+----------+------------- 2 | 1 | 張三 | 大學英語 4 | 1 | 張三 | 電影欣賞 4 | 2 | 李四 | 電影欣賞 4 | 3 | 王五 | 電影欣賞 NULL | 4 | 麻子 | NULL (5 rows)
右外鏈接實際上是一個內鏈接而後加上右表獨有的數據行,結果集中左表的字段自動補充NULL。
RIGHT OUTTER JOIN ,其中OUTTER能夠省略。
語法:
A RIGHT JOIN B ON (A.a=B.b)
A RIGHT JOIN B USING(a)
右外鏈接的結果以下圖紅色部分
示例:查詢全部課程被選狀況
test=# select * from tbl_student right join tbl_student_course using(stu_id) right join tbl_course using(course_id); course_id | stu_id | stu_name | course_name -----------+--------+----------+------------- 2 | 1 | 張三 | 大學英語 4 | 1 | 張三 | 電影欣賞 4 | 2 | 李四 | 電影欣賞 4 | 3 | 王五 | 電影欣賞 3 | NULL | NULL | 大學物理 1 | NULL | NULL | 高等數學 (6 rows)
全外鏈接實際上是一個內鏈接而後加上左表和右表獨有的數據行,左表獨有的數據行右表的字段補充NULL,右表獨有的數據行左表字段補充NULL。
FULL OUTTER JOIN,其中OUTTER能夠省略。
語法:
A FULL OUTTER JOIN B ON (A.a = B.b)
A FULL OUTTER JOIN B USING(a)
全外鏈接的結果以下圖紅色部分
示例:查詢全部學生和課程的選課信息
test=# select * from tbl_student full join tbl_student_course using(stu_id) full join tbl_course using(course_id); course_id | stu_id | stu_name | course_name -----------+--------+----------+------------- 2 | 1 | 張三 | 大學英語 4 | 1 | 張三 | 電影欣賞 4 | 2 | 李四 | 電影欣賞 4 | 3 | 王五 | 電影欣賞 NULL | 4 | 麻子 | NULL 3 | NULL | NULL | 大學物理 1 | NULL | NULL | 高等數學 (7 rows)
查詢只在左表存在的數據
示例:查詢沒有選課的學生
test=# select * from tbl_student left join tbl_student_course using(stu_id) where tbl_student_course.stu_id is null; stu_id | stu_name | course_id --------+----------+----------- 4 | 麻子 | NULL (1 row)
NOT IN存在很大的性能瓶頸,除NOT EXISTS外,也能夠使用這種查詢方式做爲替代方案。
查詢只在右表中存在的數據
示例:查詢沒有被選的課程
test=# select * from tbl_student_course right join tbl_course using(course_id) where tbl_student_course.course_id is null; course_id | stu_id | course_name -----------+--------+------------- 1 | NULL | 高等數學 3 | NULL | 大學物理 (2 rows)
查詢只在左表或只在右表存在的數據
示例:查詢沒有選課的學生和沒有被選的課程
test=# select * from tbl_student full join tbl_student_course using(stu_id) full join tbl_course using(course_id)
where tbl_student.stu_id is null or tbl_course.course_id is null;
course_id | stu_id | stu_name | course_name -----------+--------+----------+------------- NULL | 4 | 麻子 | NULL 3 | NULL | NULL | 大學物理 1 | NULL | NULL | 高等數學 (3 rows)
全部的JOIN查詢,只要理解了下面的圖,一切就OK了!
原文連接:http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins