MySQL 子查詢、內聯結、外聯結

子查詢
MySQL 子查詢版本要求:MySQL4.1引入了對子查詢的支持。
子查詢:嵌套在其他查詢語句中的查詢。

示例: 利用子查詢進行過濾
假如需要查詢出成績表分數最高的學生的姓名及編號

select st.s_no,st.s_name from student st where st.s_no in (select s1.s_no  from score s1 where s1.sc_degree  in (select max(sc.sc_degree)from score sc));


從上述查詢語句可以看出,
子查詢總是從內向外處理。爲了執行上述子查詢,MySQL實際上必須執行3條select語句,最裏面的兩個子查詢返回學生編號和最高成績,最外層查詢返回學生信息。
子查詢的查詢過程一般是通過where中的in操作符來完成,in後面子查詢語句查詢的列即爲in之前的列名。
所以在中的子句中使用子查詢,應該保證select語句具有中的子句中相同數目的列。通常,子查詢將返回單個列並且與單個列匹配。
使用子查詢,一般與IN操作符結合使用,但可以用於測試相等(=)、不相等(<>)等。

內連接,外連接實際上都是在笛卡爾積(join)的基礎上對記錄進行篩選。
內聯結inner join
外鍵:外鍵爲某個表中的一列,它包含另一個表中的主鍵值,定義了兩個表之間的關係。
內聯結語法爲:
select    查詢列表
from    表1
inner join 表2
on    連接條件

sql99語法中,內聯結分爲以下三種:
等值聯結
非等值聯結
自聯結

1、等值聯結
示例:查詢男教師及其所上的課

select tt.t_name,cc.c_name from teacher tt, course cc where  tt.t_no = cc.t_no and tt.t_sex='男';


等同於:

select tt.t_name,cc.c_name from teacher tt INNER join course cc on tt.t_no = cc.t_no where tt.t_sex='男';


image.png

select語句與前面的所有語句一樣,指定要檢索的列,此處最大的差別是所指定的列t_no 在兩個表中都有。
在聯結兩個表時,實際上要做的是將第一個表中的每一行與第二個表中的每一行進行配對。where子句作爲過濾條件,它只包含哪些匹配給條件(這裏是聯結條件)的行。沒有where子句,第一個表中的每一行將第二個表中的每個行配對,而不管他們邏輯上是否可以配在一起。這也是笛卡兒積產生的原因。

什麼是笛卡兒積?
由沒有聯結條件的表關係返回的結果爲笛卡兒積,檢索的行數將是第一個表中的行乘以第二個表中的行數。
下面這個圖很形象的描述了笛卡兒積現象

image.png

MySQL的笛卡爾積原理
1)、先確定數據要用到哪些表。
2)、將多個表先通過笛卡爾積變成一個表。
3)、然後去除不符合邏輯的數據(根據兩個表的關係去掉)。
4)、最後當做是一個虛擬表一樣來加上條件即可。

2、非等值連接 
示例:查詢工資級別的個數>20的個數,並且按工資級別降序

select salary,grade_level,count(*) from 
employees join job_grades on employees.salary
between job_grades.lowest_sal and job_grades.highest_sal
group by grade_level
having count(*)>20
order by grade_level desc;

3、自連接
示例:查詢員工的名字包含k的員工,上級的名字

select e.last_name,m.last_name
from employees e
join employees m on e.manager_id=m.employee_id
where e.last_name like '%k%';

外聯結outer join 
聯結包含了那些在相關表中沒有關聯行的行。
使用outer join 語法時,必須使用right 或left 關鍵字進行指定包括其所有行的表。
 外連接有左連接和右連接。
左聯結:查詢各表中滿足條件相同的行,並且查詢出左表的所有信息行。
右聯結:查詢各表中滿足條件相同的行,並且查詢出右表的所有信息行。

select * from course c left OUTER JOIN score  s on c.c_no = s.c_no;  //左外連接或稱左連接


image.png

select * from course c right OUTER JOIN score  s on c.c_no = s.c_no;  //右外連接或稱右連接


image.png

可以看到上述查詢結果的圖中的數據一個是9條數據,一個是8條數據。在左聯結查詢時,會將左表的所有信息給查詢出來,而有些數據在右表不存在,從而連帶出空數據。而在右聯結查詢時,則是將右表的數據查詢出來,然後連帶出左表的部分數據。

帶聚集函數的聯結
聚集函數用來彙總數據。也可以與聯結進行使用。
示例:查詢各門課程 學習的學生人數分別是多少

select s.c_no,c.c_name,count(s.c_no) 
from score s 
INNER JOIN student t on s.s_no = t.s_no   
INNER JOIN course  c on  c.c_no = s.c_no    
GROUP BY s.c_no,c.c_name ORDER BY s.c_no desc;


image.png

說明:Select 語句使用INNER JOIN 將score、student、course表相互關聯。group by 子句按課程分組數據,因此,函數調用count對每門課程學習的學生人數計數,然後返回。

總結使用聯結時要注意:
保證使用正確的聯結條件,否則將返回不正確的結果。
應該提供有效的聯結條件,否則將會產生笛卡兒積。
在一個聯結中可以包含多個表,甚至對於每個聯結可以採用不同的聯結類型。但是應該在一起測試他們之前,分別測試每個聯結。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章