13-多表查詢

本節重點:mysql

  • 多表鏈接查詢
  • 符合條件鏈接查詢
  • 子查詢

  

 

準備工做:準備兩張表,部門表(department)、員工表(employee)sql

create table department( id int, name varchar(20) ); create table employee( id int primary key auto_increment, name varchar(20), sex enum('male','female') not null default 'male', age int, dep_id int ); #插入數據
insert into department values (200,'技術'), (201,'人力資源'), (202,'銷售'), (203,'運營'); insert into employee(name,sex,age,dep_id) values ('egon','male',18,200), ('alex','female',48,201), ('wupeiqi','male',38,201), ('yuanhao','female',28,202), ('nvshen','male',18,200), ('xiaomage','female',18,204) ; # 查看錶結構和數據
mysql> desc department; +-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.19 sec) mysql> desc employee; +--------+-----------------------+------+-----+---------+----------------+
| Field  | Type                  | Null | Key | Default | Extra          |
+--------+-----------------------+------+-----+---------+----------------+
| id     | int(11)               | NO   | PRI | NULL    | auto_increment |
| name   | varchar(20)           | YES  |     | NULL    |                |
| sex    | enum('male','female') | NO   |     | male    |                |
| age    | int(11)               | YES  |     | NULL    |                |
| dep_id | int(11)               | YES  |     | NULL    |                |
+--------+-----------------------+------+-----+---------+----------------+
5 rows in set (0.01 sec) mysql> select * from department; +------+--------------+
| id   | name         |
+------+--------------+
|  200 | 技術         |
|  201 | 人力資源     |
|  202 | 銷售         |
|  203 | 運營         |
+------+--------------+
4 rows in set (0.02 sec) mysql> select * from employee; +----+----------+--------+------+--------+
| id | name     | sex    | age  | dep_id |
+----+----------+--------+------+--------+
|  1 | egon     | male   |   18 |    200 |
|  2 | alex     | female |   48 |    201 |
|  3 | wupeiqi  | male   |   38 |    201 |
|  4 | yuanhao  | female |   28 |    202 |
|  5 | nvshen   | male   |   18 |    200 |
|  6 | xiaomage | female |   18 |    204 |
+----+----------+--------+------+--------+
6 rows in set (0.00 sec)

ps:觀察兩張表,發現department表中id=203部門在employee中沒有對應的員工,發現employee中id=6的員工在department表中沒有對應關係。ide

 

 

1、多表鏈接查詢

兩張表的準備工做已完成,好比如今我要查詢的員工信息以及該員工所在的部門。從該題中,咱們看出既要查員工又要查該員工的部門,確定要將兩張表進行鏈接查詢,多表鏈接查詢。post

重點:外連接語法spa

語法:code

SELECT 字段列表 FROM 表1 INNER|LEFT|RIGHT JOIN 表2 ON 表1.字段 = 表2.字段;

 

(1)先看第一種狀況交叉鏈接:不適用任何匹配條件。生成笛卡爾積(關於笛卡爾積的含義,你們百度自行補腦)。blog

mysql> select * from employee,department; +----+----------+--------+------+--------+------+--------------+
| id | name     | sex    | age  | dep_id | id   | name         |
+----+----------+--------+------+--------+------+--------------+
|  1 | egon     | male   |   18 |    200 |  200 | 技術         |
|  1 | egon     | male   |   18 |    200 |  201 | 人力資源     |
|  1 | egon     | male   |   18 |    200 |  202 | 銷售         |
|  1 | egon     | male   |   18 |    200 |  203 | 運營         |
|  2 | alex     | female |   48 |    201 |  200 | 技術         |
|  2 | alex     | female |   48 |    201 |  201 | 人力資源     |
|  2 | alex     | female |   48 |    201 |  202 | 銷售         |
|  2 | alex     | female |   48 |    201 |  203 | 運營         |
|  3 | wupeiqi  | male   |   38 |    201 |  200 | 技術         |
|  3 | wupeiqi  | male   |   38 |    201 |  201 | 人力資源     |
|  3 | wupeiqi  | male   |   38 |    201 |  202 | 銷售         |
|  3 | wupeiqi  | male   |   38 |    201 |  203 | 運營         |
|  4 | yuanhao  | female |   28 |    202 |  200 | 技術         |
|  4 | yuanhao  | female |   28 |    202 |  201 | 人力資源     |
|  4 | yuanhao  | female |   28 |    202 |  202 | 銷售         |
|  4 | yuanhao  | female |   28 |    202 |  203 | 運營         |
|  5 | nvshen   | male   |   18 |    200 |  200 | 技術         |
|  5 | nvshen   | male   |   18 |    200 |  201 | 人力資源     |
|  5 | nvshen   | male   |   18 |    200 |  202 | 銷售         |
|  5 | nvshen   | male   |   18 |    200 |  203 | 運營         |
|  6 | xiaomage | female |   18 |    204 |  200 | 技術         |
|  6 | xiaomage | female |   18 |    204 |  201 | 人力資源     |
|  6 | xiaomage | female |   18 |    204 |  202 | 銷售         |
|  6 | xiaomage | female |   18 |    204 |  203 | 運營         |

 

(2)內鏈接:只鏈接匹配的行資源

 

#找兩張表共有的部分,至關於利用條件從笛卡爾積結果中篩選出了匹配的結果 #department沒有204這個部門,於是employee表中關於204這條員工信息沒有匹配出來
mysql> select employee.id,employee.name,employee.age,employee.sex,department.name from employee inner join department on employee.dep_id=department.id; +----+---------+------+--------+--------------+
| id | name    | age  | sex    | name         |
+----+---------+------+--------+--------------+
|  1 | egon    |   18 | male   | 技術         |
|  2 | alex    |   48 | female | 人力資源     |
|  3 | wupeiqi |   38 | male   | 人力資源     |
|  4 | yuanhao |   28 | female | 銷售         |
|  5 | nvshen  |   18 | male   | 技術         |
+----+---------+------+--------+--------------+
5 rows in set (0.00 sec) #上述sql等同於
mysql> select employee.id,employee.name,employee.age,employee.sex,department.name from employee,department where employee.dep_id=department.id;

 

(3)外連接之左鏈接:優先顯示左表所有記錄rem

#以左表爲準,即找出全部員工信息,固然包括沒有部門的員工 #本質就是:在內鏈接的基礎上增長左邊有,右邊沒有的結果
mysql> select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id; +----+----------+--------------+
| id | name     | depart_name  |
+----+----------+--------------+
|  1 | egon     | 技術         |
|  5 | nvshen   | 技術         |
|  2 | alex     | 人力資源     |
|  3 | wupeiqi  | 人力資源     |
|  4 | yuanhao  | 銷售         |
|  6 | xiaomage | NULL         |
+----+----------+--------------+
6 rows in set (0.00 sec)

(4) 外連接之右鏈接:優先顯示右表所有記錄io

#以右表爲準,即找出全部部門信息,包括沒有員工的部門 #本質就是:在內鏈接的基礎上增長右邊有,左邊沒有的結果
mysql> select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id; +------+---------+--------------+
| id   | name    | depart_name  |
+------+---------+--------------+
|    1 | egon    | 技術         |
|    2 | alex    | 人力資源     |
|    3 | wupeiqi | 人力資源     |
|    4 | yuanhao | 銷售         |
|    5 | nvshen  | 技術         |
| NULL | NULL    | 運營         |
+------+---------+--------------+
6 rows in set (0.00 sec)

 

(5) 全外鏈接:顯示左右兩個表所有記錄(瞭解)

#外鏈接:在內鏈接的基礎上增長左邊有右邊沒有的和右邊有左邊沒有的結果 #注意:mysql不支持全外鏈接 full JOIN #強調:mysql可使用此種方式間接實現全外鏈接
語法:select * from employee left join department on employee.dep_id = department.id union all select * from employee right join department on employee.dep_id = department.id; mysql> select * from employee left join department on employee.dep_id = department.id union select * from employee right join department on employee.dep_id = department.id ; +------+----------+--------+------+--------+------+--------------+
| id   | name     | sex    | age  | dep_id | id   | name         |
+------+----------+--------+------+--------+------+--------------+
|    1 | egon     | male   |   18 |    200 |  200 | 技術         |
|    5 | nvshen   | male   |   18 |    200 |  200 | 技術         |
|    2 | alex     | female |   48 |    201 |  201 | 人力資源     |
|    3 | wupeiqi  | male   |   38 |    201 |  201 | 人力資源     |
|    4 | yuanhao  | female |   28 |    202 |  202 | 銷售         |
|    6 | xiaomage | female |   18 |    204 | NULL | NULL         |
| NULL | NULL     | NULL   | NULL |   NULL |  203 | 運營         |
+------+----------+--------+------+--------+------+--------------+
7 rows in set (0.01 sec) #注意 union與union all的區別:union會去掉相同的紀錄

 

 

2、符合條件鏈接查詢

示例1:之內鏈接的方式查詢employee和department表,而且employee表中的age字段值必須大於25,即找出年齡大於25歲的員工以及員工所在的部門

select employee.name,department.name from employee inner join department   on employee.dep_id = department.id   where age > 25;

 

示例2:之內鏈接的方式查詢employee和department表,而且以age字段的升序方式顯示。

select employee.id,employee.name,employee.age,department.name from employee,department where employee.dep_id = department.id and age > 25 order by age asc;

 

3、子查詢

#1:子查詢是將一個查詢語句嵌套在另外一個查詢語句中。 #2:內層查詢語句的查詢結果,能夠爲外層查詢語句提供查詢條件。 #3:子查詢中能夠包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等關鍵字 #4:還能夠包含比較運算符:= 、 !=、> 、<等

 

例子:

(1)帶in關鍵字的子查詢

#查詢平均年齡在25歲以上的部門名
select id,name from department where id in (select dep_id from employee group by dep_id having avg(age) > 25); # 查看技術部員工姓名
select name from employee where dep_id in (select id from department where name='技術'); #查看不足1人的部門名
select name from department where id not in (select dep_id from employee group by dep_id);

 

(2)帶比較運算符的子查詢

#比較運算符:=、!=、>、>=、<、<=、<> #查詢大於全部人平均年齡的員工名與年齡
mysql> select name,age from employee where age > (select avg(age) from employee); +---------+------+
| name    | age  |
+---------+------+
| alex    |   48 |
| wupeiqi |   38 |
+---------+------+

#查詢大於部門內平均年齡的員工名、年齡
思路: (1)先對員工表(employee)中的人員分組(group by),查詢出dep_id以及平均年齡。
(2)將查出的結果做爲臨時表,再對根據臨時表的dep_id和employee的dep_id做爲篩選條件將employee表和臨時表進行內鏈接。 (3)最後再將employee員工的年齡是大於平均年齡的員工名字和年齡篩選。 mysql
> select t1.name,t1.age from employee as t1 inner join (select dep_id,avg(age) as avg_age from employee group by dep_id) as t2 on t1.dep_id = t2.dep_id where t1.age > t2.avg_age; +------+------+ | name | age | +------+------+ | alex | 48 |

 

(3)帶EXISTS關鍵字的子查詢

#EXISTS關字鍵字表示存在。在使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄。而是返回一個真假值。True或False #當返回True時,外層查詢語句將進行查詢;當返回值爲False時,外層查詢語句不進行查詢 #department表中存在dept_id=203,Ture
mysql> select * from employee  where exists (select id from department where id=200); +----+----------+--------+------+--------+
| id | name     | sex    | age  | dep_id |
+----+----------+--------+------+--------+
|  1 | egon     | male   |   18 |    200 |
|  2 | alex     | female |   48 |    201 |
|  3 | wupeiqi  | male   |   38 |    201 |
|  4 | yuanhao  | female |   28 |    202 |
|  5 | nvshen   | male   |   18 |    200 |
|  6 | xiaomage | female |   18 |    204 |
+----+----------+--------+------+--------+
#department表中存在dept_id=205,False
mysql> select * from employee  where exists (select id from department where id=204); Empty set (0.00 sec)

小練習:

查詢每一個部門最新入職的那位員工

#建立表
create table employee( id int not null unique auto_increment, name varchar(20) not null, sex enum('male','female') not null default 'male', #大部分是男的
age int(3) unsigned not null default 28, hire_date date not null, post varchar(50), post_comment varchar(100), salary double(15,2), office int, #一個部門一個屋子
depart_id int ); #查看錶結構
mysql> desc employee; +--------------+-----------------------+------+-----+---------+----------------+
| Field        | Type                  | Null | Key | Default | Extra          |
+--------------+-----------------------+------+-----+---------+----------------+
| id           | int(11)               | NO   | PRI | NULL    | auto_increment |
| name         | varchar(20)           | NO   |     | NULL    |                |
| sex          | enum('male','female') | NO   |     | male    |                |
| age          | int(3) unsigned       | NO   |     | 28      |                |
| hire_date    | date                  | NO   |     | NULL    |                |
| post         | varchar(50)           | YES  |     | NULL    |                |
| post_comment | varchar(100)          | YES  |     | NULL    |                |
| salary       | double(15,2)          | YES  |     | NULL    |                |
| office       | int(11)               | YES  |     | NULL    |                |
| depart_id    | int(11)               | YES  |     | NULL    |                |
+--------------+-----------------------+------+-----+---------+----------------+

#插入記錄 #三個部門:教學,銷售,運營
insert into employee(name,sex,age,hire_date,post,salary,office,depart_id) values ('egon','male',18,'20170301','老男孩駐沙河辦事處外交大使',7300.33,401,1), #如下是教學部
('alex','male',78,'20150302','teacher',1000000.31,401,1), ('wupeiqi','male',81,'20130305','teacher',8300,401,1), ('yuanhao','male',73,'20140701','teacher',3500,401,1), ('liwenzhou','male',28,'20121101','teacher',2100,401,1), ('jingliyang','female',18,'20110211','teacher',9000,401,1), ('jinxin','male',18,'19000301','teacher',30000,401,1), ('成龍','male',48,'20101111','teacher',10000,401,1), ('歪歪','female',48,'20150311','sale',3000.13,402,2),#如下是銷售部門
('丫丫','female',38,'20101101','sale',2000.35,402,2), ('丁丁','female',18,'20110312','sale',1000.37,402,2), ('星星','female',18,'20160513','sale',3000.29,402,2), ('格格','female',28,'20170127','sale',4000.33,402,2), ('張野','male',28,'20160311','operation',10000.13,403,3), #如下是運營部門
('程咬金','male',18,'19970312','operation',20000,403,3), ('程咬銀','female',18,'20130311','operation',19000,403,3), ('程咬銅','male',18,'20150411','operation',18000,403,3), ('程咬鐵','female',18,'20140512','operation',17000,403,3) ;
select * from employee as t1 inner join (select post,max(hire_date) as new_date from employee group by post) as t2 on t1.post=t2.post where t1.hire_date=t2.new_date;
小練習答案
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息