数据库--多表查询
文章目錄
- 數據庫--多表查詢
- 5.2多表查詢概述
- 5.2.1 數據準備
- 5.2.2 概述
- 5.2.3 分類
- 5.3 內連接
- 1). 隱式內連接
- 2). 顯式內連接
- 案例:
- 5.4 外連接
- 1). 左外連接
- 2). 右外連接
- 案例:
- 5.5 自連接
- 5.5.1 自連接查詢
- 案例:
- 5.5.2 聯合查詢
- union查詢
- 案例:
- 5.6 子查詢
- 5.6.1 概述
- 1). 概念
- 2). 分類
- 5.6.2 標量子查詢
- 概述
- 案例:
- 5.6.3 列子查詢
- 概述
- 案例:
- 5.6.4 行子查詢
- 概述
- 案例:
- 5.6.5 表子查詢
- 概述
- 案例:
- 5.7 多表查詢案例
數據庫–多表查詢
5.2多表查詢概述
5.2.1 數據準備
執行如下腳本,創建emp表與dept表并插入測試數據
-- 創建dept表,并插入數據 create table dept( id int auto_increment comment 'ID' primary key, name varchar(50) not null comment '部門名稱' )comment '部門表'; INSERT INTO dept (id, name) VALUES (1, '研發部'), (2, '市場部'),(3, '財務部'), (4, '銷售部'), (5, '總經辦'), (6, '人事部'); -- 創建emp表,并插入數據 create table emp( id int auto_increment comment 'ID' primary key, name varchar(50) not null comment '姓名', age int comment '年齡', job varchar(20) comment '職位', salary int comment '薪資', entrydate date comment '入職時間', managerid int comment '直屬領導ID', dept_id int comment '部門ID' )comment '員工表'; -- 添加外鍵 alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id); INSERT INTO emp (id, name, age, job,salary, entrydate, managerid, dept_id) VALUES (1, '金庸', 66, '總裁',20000, '2000-01-01', null,5), (2, '張無忌', 20, '項目經理',12500, '2005-12-05', 1,1), (3, '楊逍', 33, '開發', 8400,'2000-11-03', 2,1), (4, '韋一笑', 48, '開發',11000, '2002-02-05', 2,1), (5, '常遇春', 43, '開發',10500, '2004-09-07', 3,1), (6, '小昭', 19, '程序員鼓勵師',6600, '2004-10-12', 2,1), (7, '滅絕', 60, '財務總監',8500, '2002-09-12', 1,3), (8, '周芷若', 19, '會計',48000, '2006-06-02', 7,3), (9, '丁敏君', 23, '出納',5250, '2009-05-13', 7,3), (10, '趙敏', 20, '市場部總監',12500, '2004-10-12', 1,2), (11, '鹿杖客', 56, '職員',3750, '2006-10-03', 10,2), (12, '鶴筆翁', 19, '職員',3750, '2007-05-09', 10,2), (13, '方東白', 19, '職員',5500, '2009-02-12', 10,2), (14, '張三豐', 88, '銷售總監',14000, '2004-10-12', 1,4), (15, '俞蓮舟', 38, '銷售',4600, '2004-10-12', 14,4), (16, '宋遠橋', 40, '銷售',4600, '2004-10-12', 14,4), (17, '陳友諒', 42, null,2000, '2011-10-12', 1,null);dept表共6條記錄,emp表共17條記錄。
5.2.2 概述
多表查詢就是指從多張表中查詢數據。
原來查詢單表數據,執行的SQL形式為:
select * from emp;那么我們要執行多表查詢,就只需要使用逗號分隔多張表即可,如:
select * from emp , dept;5.2.3 分類
- 連接查詢
- 子查詢
5.3 內連接
內連接查詢的是兩張表交集部分的數據。
內連接的語法分為兩種: 隱式內連接、顯式內連接。
1). 隱式內連接
SELECT 字段列表 FROM 表1 , 表2 WHERE 條件 ... ;2). 顯式內連接
SELECT 字段列表 FROM 表1 [ INNER ] JOIN 表2 ON 連接條件 ... ;案例:
A. 查詢每一個員工的姓名 , 及關聯的部門的名稱 (隱式內連接實現)
表結構: emp , dept
連接條件: emp.dept_id = dept.id
B. 查詢每一個員工的姓名 , 及關聯的部門的名稱 (顯式內連接實現) — INNER JOIN …
ON …
表結構: emp , dept
連接條件: emp.dept_id = dept.id
表的別名:
①. tablea as 別名1 , tableb as 別名2 ;
②. tablea 別名1 , tableb 別名2 ;
注意事項:
一旦為表起了別名,就不能再使用表名來指定對應的字段了,此時只能夠使用別名來指定字
段。
5.4 外連接
外連接分為兩種,分別是:左外連接 和 右外連接。具體的語法結構為:
1). 左外連接
SELECT 字段列表 FROM 表1 LEFT [ OUTER ] JOIN 表2 ON 條件 ... ;左外連接相當于查詢表1(左表)的所有數據,當然也包含表1和表2交集部分的數據。
2). 右外連接
SELECT 字段列表 FROM 表1 RIGHT [ OUTER ] JOIN 表2 ON 條件 ... ;右外連接相當于查詢表2(右表)的所有數據,當然也包含表1和表2交集部分的數據。
案例:
A. 查詢emp表的所有數據, 和對應的部門信息
由于需求中提到,要查詢emp的所有數據,所以是不能內連接查詢的,需要考慮使用外連接查詢。
表結構: emp, dept
連接條件: emp.dept_id = dept.id
B. 查詢dept表的所有數據, 和對應的員工信息(右外連接)
由于需求中提到,要查詢dept表的所有數據,所以是不能內連接查詢的,需要考慮使用外連接查詢
表結構: emp, dept
連接條件: emp.dept_id = dept.id
注意事項:
左外連接和右外連接是可以相互替換的,只需要調整在連接查詢時SQL中,表結構的先后順
序就可以了。而我們在日常開發使用時,更偏向于左外連接。
5.5 自連接
5.5.1 自連接查詢
自連接查詢,顧名思義,就是自己連接自己,也就是把一張表連接查詢多次。我們先來學習一下自連接的查詢語法:
SELECT 字段列表 FROM 表A 別名A JOIN 表A 別名B ON 條件 ... ;而對于自連接查詢,可以是內連接查詢,也可以是外連接查詢。
案例:
A. 查詢員工 及其 所屬領導的名字
表結構: emp
B. 查詢所有員工 emp 及其領導的名字 emp , 如果員工沒有領導, 也需要查詢出來
表結構: emp a , emp b
注意事項:
在自連接查詢中,必須要為表起別名,要不然我們不清楚所指定的條件、返回的字段,到底
是哪一張表的字段。
5.5.2 聯合查詢
union查詢
就是把多次查詢的結果合并起來,形成一個新的查詢結果集。
SELECT 字段列表 FROM 表A ... UNION [ ALL ] SELECT 字段列表 FROM 表B ....;對于聯合查詢的多張表的列數必須保持一致,字段類型也需要保持一致。
union all 會將全部的數據直接合并在一起,union 會對合并之后的數據去重。
案例:
A. 將薪資低于 5000 的員工 , 和 年齡大于 50 歲的員工全部查詢出來.
當前對于這個需求,我們可以直接使用多條件查詢,使用邏輯運算符 or 連接即可。 那這里呢,我們
也可以通過union/union all來聯合查詢.
5.6 子查詢
5.6.1 概述
1). 概念
SQL語句中嵌套SELECT語句,稱為嵌套查詢,又稱子查詢。
SELECT * FROM t1 WHERE column1 = ( SELECT column1 FROM t2 );子查詢外部的語句可以是INSERT / UPDATE / DELETE / SELECT 的任何一個。
2). 分類
根據子查詢結果不同,分為:
A. 標量子查詢(子查詢結果為單個值)
B. 列子查詢(子查詢結果為一列)
C. 行子查詢(子查詢結果為一行)
D. 表子查詢(子查詢結果為多行多列)
根據子查詢位置,分為:
A. WHERE之后
B. FROM之后
C. SELECT之后
5.6.2 標量子查詢
概述
子查詢返回的結果是單個值(數字、字符串、日期等),最簡單的形式,這種子查詢稱為標量子查詢。
常用的操作符:= <> > >= < <=
案例:
A. 查詢 “銷售部” 的所有員工信息
完成這個需求時,我們可以將需求分解為兩步:
①. 查詢 “銷售部” 部門ID
select id from dept where name = '銷售部';②. 根據 “銷售部” 部門ID, 查詢員工信息
select * from emp where dept_id = (select id from dept where name = '銷售部');B. 查詢在 “方東白” 入職之后的員工信息
完成這個需求時,我們可以將需求分解為兩步:
①. 查詢 方東白 的入職日期
②. 查詢指定入職日期之后入職的員工信息
select * from emp where entrydate > (select entrydate from emp where name = '方東白');5.6.3 列子查詢
概述
子查詢返回的結果是一列(可以是多行),這種子查詢稱為列子查詢。
常用的操作符:IN 、NOT IN 、 ANY 、 ALL
| IN | 在指定的集合范圍之內,多選一 |
| NOT IN | 不在指定的集合范圍之內 |
| ANY | 子查詢返回列表中,有任意一個滿足即可 |
| ALL | 子查詢返回列表的所有值都必須滿足 |
案例:
A. 查詢 “銷售部” 和 “市場部” 的所有員工信息
分解為以下兩步:
①. 查詢 “銷售部” 和 “市場部” 的部門ID
select id from dept where name = '銷售部' or name = '市場部';②. 根據部門ID, 查詢員工信息
select * from emp where dept_id in (select id from dept where name = '銷售部' orname = '市場部');B. 查詢比 財務部 所有人工資都高的員工信息
分解為以下兩步:
①. 查詢所有 財務部 人員工資
select id from dept where name = '財務部';select salary from emp where dept_id = (select id from dept where name = '財務部');②. 比 財務部 所有人工資都高的員工信息
select * from emp where salary > all ( select salary from emp where dept_id = (select id from dept where name = '財務部') );C. 查詢比研發部其中任意一人工資高的員工信息
分解為以下兩步:
①. 查詢研發部所有人工資
select salary from emp where dept_id = (select id from dept where name = '研發部');②. 比研發部其中任意一人工資高的員工信息
select * from emp where salary > any ( select salary from emp where dept_id = (select id from dept where name = '研發部') );5.6.4 行子查詢
概述
子查詢返回的結果是一行(可以是多列),這種子查詢稱為行子查詢。
常用的操作符:= 、<> 、IN 、NOT IN
案例:
A. 查詢與 “張無忌” 的薪資及直屬領導相同的員工信息 ;
這個需求同樣可以拆解為兩步進行:
①. 查詢 “張無忌” 的薪資及直屬領導
select salary, managerid from emp where name = '張無忌';②. 查詢與 “張無忌” 的薪資及直屬領導相同的員工信息 ;
select * from emp where (salary,managerid) = (select salary, managerid from emp where name = '張無忌');5.6.5 表子查詢
概述
子查詢返回的結果是多行多列,這種子查詢稱為表子查詢。
常用的操作符:IN
案例:
A. 查詢與 “鹿杖客” , “宋遠橋” 的職位和薪資相同的員工信息
分解為兩步執行:
①. 查詢 “鹿杖客” , “宋遠橋” 的職位和薪資
elect job, salary from emp where name = '鹿杖客' or name = '宋遠橋';②. 查詢與 “鹿杖客” , “宋遠橋” 的職位和薪資相同的員工信息
select * from emp where (job,salary) in ( select job, salary from emp where name ='鹿杖客' or name = '宋遠橋' );B. 查詢入職日期是 “2006-01-01” 之后的員工信息 , 及其部門信息
①. 入職日期是 “2006-01-01” 之后的員工信息
select * from emp where entrydate > '2006-01-01';②. 查詢這部分員工, 對應的部門信息;
select e.*, d.* from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.dept_id = d.id ;5.7 多表查詢案例
數據環境準備:
create table salgrade( grade int, losal int, hisal int ) comment '薪資等級表'; insert into salgrade values (1,0,3000); insert into salgrade values (2,3001,5000); insert into salgrade values (3,5001,8000); insert into salgrade values (4,8001,10000); insert into salgrade values (5,10001,15000); insert into salgrade values (6,15001,20000); insert into salgrade values (7,20001,25000); insert into salgrade values (8,25001,30000);在這個案例中,我們主要運用上面所講解的多表查詢的語法,完成以下的12個需求即可,而這里主要涉
及到的表就三張:emp員工表、dept部門表、salgrade薪資等級表 。
1). 查詢員工的姓名、年齡、職位、部門信息 (隱式內連接)
表: emp , dept
連接條件: emp.dept_id = dept.id
2). 查詢年齡小于30歲的員工的姓名、年齡、職位、部門信息(顯式內連接)
表: emp , dept
連接條件: emp.dept_id = dept.id
3). 查詢擁有員工的部門ID、部門名稱
表: emp , dept
連接條件: emp.dept_id = dept.id
4). 查詢所有年齡大于40歲的員工, 及其歸屬的部門名稱; 如果員工沒有分配部門, 也需要展示出
來(外連接)
表: emp , dept
連接條件: emp.dept_id = dept.id
5). 查詢所有員工的工資等級
表: emp , salgrade
連接條件 : emp.salary >= salgrade.losal and emp.salary <= salgrade.hisal
6). 查詢 “研發部” 所有員工的信息及 工資等級
表: emp , salgrade , dept
連接條件 : emp.salary between salgrade.losal and salgrade.hisal ,
emp.dept_id = dept.id
查詢條件 : dept.name = ‘研發部’
7). 查詢 “研發部” 員工的平均工資
select avg(e.salary) from emp e, dept d where e.dept_id = d.id and d.name = '研發部';8). 查詢工資比 “滅絕” 高的員工信息。
①. 查詢 “滅絕” 的薪資
select salary from emp where name = '滅絕';②. 查詢比她工資高的員工數據
select * from emp where salary > ( select salary from emp where name = '滅絕' );9). 查詢比平均薪資高的員工信息
①. 查詢員工的平均薪資
select avg(salary) from emp;②. 查詢比平均薪資高的員工信息
select * from emp where salary > ( select avg(salary) from emp );10). 查詢低于本部門平均工資的員工信息
①. 查詢指定部門平均薪資
select avg(e1.salary) from emp e1 where e1.dept_id = 1; select avg(e1.salary) from emp e1 where e1.dept_id = 2;②. 查詢低于本部門平均工資的員工信息
select * from emp e2 where e2.salary < ( select avg(e1.salary) from emp e1 where e1.dept_id = e2.dept_id );11). 查詢所有的部門信息, 并統計部門的員工人數
select d.id, d.name , ( select count(*) from emp e where e.dept_id = d.id ) '人數'from dept d;12). 查詢所有學生的選課情況, 展示出學生名稱, 學號, 課程名稱
表: student , course , student_course
連接條件: student.id = student_course.studentid , course.id =
student_course.courseid
總結
- 上一篇: IEC 6-1131/3的5种标准编程语
- 下一篇: Leetcode143. Reorder