6.多表查詢
a.連接查詢
1.連接查詢
-
1.1多表連接,跨表查詢
-
1.2分類:sql92,sql99
-
1.3 表連接分類:
- 內連接:等值連接、非等值連接、自連接,
- 外連接:左外連接(左連接)、右外連接(右連接),
- 全連接
2.笛卡爾積
當兩張表進行連接查詢,沒有任何條件限制的,最終查詢結果條數,是兩張表條數的乘積,這種現象被稱為:笛卡爾積
select ename,dname from emp,dept;
-
1.5如何避免笛卡爾積現象 (sql92語法)
-
雖然使用where 進行條件篩選,但是並沒有減少匹配此次
-
表的連接次數越多,效率越低,盡量避免表的連接
select ename,dname from emp,dept where emp.deptno=dept.deptno; 通過設定條件(sql92語法)
-- 優化
select emp.ename,dept.dname from emp,dept where emp.deptno=dept.deptno;
-- 使用別名進行進一步優化,提供效率
select e.ename,d.dname from emp e,dept d where e.deptno= d.deptno;
3.內連接- 等值連接(條件是等量關系故稱等值連接) inner
案例:查詢每個員工所在部門名稱,顯示員工名和部門名
emp e 和dep d 表進行連接。條件是e.deptno = d.deptno
-- sql 92語法
select e.ename,d.dname from emp e,dept d where e.deptno=d.deptno
-- sql 99語法 join 前inner 可省略
select
e.ename,d.dname
from
emp e
join
dept d
on
e.deptno= d.deptno;
- sql92缺點:結構不清晰,表的連接條件,和后期進一步篩選的條件,都放在where后面
- sql99優點:表連接的條件是獨立的,連接之后,如果還需進一步篩選,再往后繼續添加where
4.內連接- 非等值連接
條件不是一個等量關系,稱為非等值連接
范圍、等級、取值區間關聯,使用between.. and..
-- between .. and
select
e.ename,e.sal,s.grade
from
emp e
join
salgrade s
on
e.sal between s.losal and s.hisal;
5.內連接 -自連接
技巧:把一張表,看成兩張表
對emp 領導表內進行自連接,需要把emp 表既看成員工表,也看成領導表
empno | ename | mgr |
---|---|---|
7369 | smith | 7902 |
7499 | allen | 7698 |
7698 | blark | 7839 |
7902 | ford | 7566 |
--
select
a.ename as '員工名', b.ename as'領導名'
from
emp a
join
emp b
on
a.mgr=b.empno;
-- 員工的領導編號 = 領導的員工編號
6.外連接
-
右外連接 right join
右表為主表,將右表全部查詢出來,捎帶關聯左邊的表
在外鏈接當中,兩張表連接,產生了主次關系。
-
左外連接亦然 left join
-- 右外連接
-- 可帶outer 帶上可讀性更強
select
e.ename,d.dname
from
emp e
right outer join
dept d -- 右邊全部匹配
on
e.deptno= d.deptno;
總結 外連接的查詢結果條數一定是>=內連接的查詢結果條數
7.三張表,四張表連接
-- 語法:
select
...
from
a
join
b
on
a和b的連接條件
join
c
on
a和c的條件
join
d
on
a和d的條件
-- 一條sql中內連接和外連接可以混合,都可以出現
案例:
找出每個員工的部門名稱以及工資等級,要求顯示員工名、部門名、薪資、薪資等級
如果再加上查詢員工的上級領導(使用外連接,避免刪除)
分析:從emp 取出ename, 關聯dept,取dname, 關聯salgrade 取grade
emp | |||
---|---|---|---|
empno | ename | sal | depton |
7398 | smith | 800.00 | 20 |
7499 | allen | 1600.00 | 30 |
7521 | ward | 1250.00 | 30 |
7654 | martin | 1250.00 | 30 |
dept | ||
---|---|---|
deptno | dname | loc |
10 | accounting | new york |
20 | research | dallas |
30 | sales | chicago |
40 | operations | boston |
salgrde | ||
---|---|---|
grade | losal | hisal |
1 | 700 | 1200 |
2 | 1201 | 1400 |
3 | 1401 | 2000 |
4 | 2001 | 3000 |
select e.ename,d.dname,s.grade
from emp e
join dept d
on e.depton = d.depton.deptno
join salgrade s
on e.sal between s.losal and s.hisal;
b.子查詢
1.子查詢
select 語句中嵌套select 語句,被嵌套的select 的語句稱為子查詢
2.where 條件后的子查詢
-- 子查詢1,where條件中
select 表頭a from 表a where 表頭 .. (select .. from table_b)
3.from 子語句中的子查詢 (可以將子查詢的結果當做一張臨時表)
-- from 子句中的子查詢
from 后面的子查詢,可以將子查詢的查詢結果當做一張臨時表。(技巧)
__注意__子查詢注意分組函數的使用時易被錯認為函數,導致報錯,需要對該分組函數命名
4.select 后面出現的子查詢
select 按表行搜索,類似循環嵌套,(使用聯表進行查詢)
-
select 后面出現的子查詢只能返回一條結果,多於一條報錯
-- 實例 理解: 查詢emp表,分別查詢e對應的ename列,deptno列,以及e第一行中對應的deptno 對應d表中的dname, select e.ename,e,deptno (select d.dname from dept d where e.deptno=d.deptno) as dname from emp e;
-
實例 查詢各科成績前三名的記錄:(不考慮成績並列情況)
select score.sid,score.course_id,score.num,T.first_num,T.second_num from score left join
(select
sid,
(select num from score as s2 where s2.course_id = s1.course_id order by num desc limit 0,1) as first_num,
(select num from score as s2 where s2.course_id = s1.course_id order by num desc limit 3,1) as second_num
from
score as s1
) as T
on score.sid =T.sid
where score.num <= T.first_num and score.num >= T.second_num;
c.union 合並查詢結果集
- union 進行結果集合並要求結果集的列數相同,合並時列與列的數據類型也相同
- 同時union合並時會自動去重,可以使用union all 進行保留
- 減少匹配次數,實現數據集的拼接
- union的效率要高一些(減少匹配次數),對於表連接而言,每連接一次新表,則匹配的次數滿足笛卡爾積
- 實例:
查詢工作崗位是manager 和salesman的員工
-- 第一種
select ename,job from emp where job='manager' or 'salesman';
-- 第二種
select ename,job from emp where job in ('manager','salesman');
- 使用union 進行合並
select ename,job from emp where job ='manager'
union
select ename,job from emp where job = 'salesman';
D、limit 分頁查詢
1.將數據集的一部分取出,通常使用在分頁查詢當中
-
語法
完整用法:limit startindex,length startindex 起始下標 length 長度 起始下標從0開始 缺省用法:limit num; 取前num個 limit 8 表示取前八個
-
limit 與oder by的使用
select ... from... order by .. desc limit 5
2.通用分頁
- 每頁顯示3條記錄
- 第1頁 : limit 0,3
- 第2頁: limit 3,3
- 第3頁: limit 6,3
- 第4頁: limit 9,3
- 第n頁: limit (num-1)*3,3