mysql四-2:多表查詢
新建表
mysql> create table department(
id int,
name varchar(20)
);
mysql> 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
);
插入數據
mysql> insert into department values
(200,'技術'),
(201,'人力資源'),
(202,'銷售'),
(203,'運營');
mysql> 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),
('liwenzhou','male',18,200),
('jingliyang','female',18,204)
;
查看表結構和數據
mysql> desc department;
mysql> desc employee;
mysql> select * from department;
mysql> select * from employee;
二、多表連接查詢
重點!!!外鏈接語法
ELECT 字段列表 FROM 表1 INNER|LEFT|RIGHT JOIN 表2 ON 表1.字段 = 表2.字段;
1、交叉連接:不適用任何匹配條件。生成笛卡爾積
mysql> select * from employee,department;
2、內連接:只連接匹配的行
找兩張表共有的部分,相當於利用條件從笛卡爾積結果中篩選出了正確的結果
select employee.id,employee.name,employee.age,employee.sex,department.name from employee inner join department on employee.dep_id=department.id;
上述sql等同於
select employee.id,employee.name,employee.age,employee.sex,department.name from employee,department where employee.dep_id=department.id;
註意:department沒有204這個部門,因而employee表中關於204這條員工信息沒有匹配出來
3、外鏈接之左連接:優先顯示左表全部記錄
以左表為準,即找出所有員工信息,當然包括沒有部門的員工;本質就是:在內連接的基礎上增加左邊有右邊沒有的結果
select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id;
4、外鏈接之右連接:優先顯示右表全部記錄
以右表為準,即找出所有部門信息,包括沒有員工的部門;本質就是:在內連接的基礎上增加右邊有左邊沒有的結果
select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id;
5、全外連接:顯示左右兩個表全部記錄
在內連接的基礎上增加左邊有右邊沒有的和右邊有左邊沒有的結果
註意:mysql不支持全外連接 full JOIN
強調: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;
註意 union與union all的區別:union會去掉相同的紀錄
三、符合條件連接查詢
示例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;
四 子查詢
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人的部門名(子查詢得到的是有人的部門id)
select name from department where id not in (select distinct dep_id from employee);
2、帶比較運算符的子查詢
比較運算符:=、!=、>、>=、<、<=、<>
查詢大於所有人平均年齡的員工名與年齡
select name,age from emp where age > (select avg(age) from emp);
查詢大於部門內平均年齡的員工名、年齡
select t1.name,t1.age from emp t1 inner join (select dep_id,avg(age) avg_age from emp group by dep_id) t2 on t1.dep_id = t2.dep_id where t1.age > t2.avg_age;
3、帶EXISTS關鍵字的子查詢
EXISTS關字鍵字表示存在。在使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄。而是返回一個真假值。True或False,當返回True時,外層查詢語句將進行查詢;當返回值為False時,外層查詢語句不進行查詢
department表中存在dept_id=203,Ture
select * from employee where exists (select id from department where id=200);
department表中存在dept_id=205,False
select * from employee where exists (select id from department where id=204);
4、練習:查詢每個部門最新入職的那位員工
準備表:
mysql>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>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)
;
答案1:鏈表
SELECT * FROM employee AS t1 INNER JOIN (
SELECT post,max(hire_date) max_date FROM employee GROUP BY post ) AS t2 ON t1.post = t2.post
WHERE t1.hire_date = t2.max_date;
答案2:子查詢
select t3.name,t3.post,t3.hire_date from employee as t3 where id in (select (select id from employee as t2 where t2.post=t1.post order by hire_date desc limit 1) from employee as t1 group by post);
五、綜合練習
1、準備表、記錄
mysql> create database db1;
mysql> use db1;
mysql> source /root/init.sql (從init.sql文件中導入數據)
2、題目
1)查詢所有的課程的名稱以及對應的任課老師姓名
select
teacher.tname,
course.cname
from
teacher
inner join course on teacher.tid = course.teacher_id;
2)查詢學生表中男女生各有多少人
select gender,count(sid) from student group by gender;
3)查詢物理成績等於100的學生的姓名
select
student.sname
from
student
where
sid in (
select
student_id
from
score
inner join course on score.course_id = course.cid
WHERE
course.cname = '物理' AND score.num = 100);
4)查詢平均成績大於八十分的同學的姓名和平均成績
select
student.sname,
t1.avg_num
from
student
inner join (
select
student_id
avg(num) AS avg_num
from
score
group by
student_id
having
avg(num) > 80
)AS t1 on student.sid=t1.student_id;
5)查詢所有學生的學號,姓名,選課數,總成績
SELECT
student.sid,
student.sname,
t1.course_num,
t1.total_num
FROM
student
LEFT JOIN (
SELECT
student_id,
COUNT(course_id) course_num,
sum(num) total_num
FROM
score
GROUP BY
student_id
) AS t1 ON student.sid = t1.student_id;
6)查詢姓李老師的個數
select count(tid) from teacher where tname LIKE '李%';
7)查詢沒有報李平老師課的學生姓名
select
student.sname
from
student
8)查詢物理課程比生物課程高的學生的學號
9)查詢沒有同時選修物理課程和體育課程的學生姓名
10)查詢掛科超過兩門(包括兩門)的學生姓名和班級
11)查詢選修了所有課程的學生姓名
12)查詢李平老師教的課程的所有成績記錄
13)查詢全部學生都選修了的課程號和課程名
14)查詢每門課程被選修的次數
15)查詢之選修了一門課程的學生姓名和學號
16)查詢所有學生考出的成績並按從高到低排序(成績去重)
17)查詢平均成績大於85的學生姓名和平均成績
18)查詢生物成績不及格的學生姓名和對應生物分數
19)查詢在所有選修了李平老師課程的學生中,這些課程(李平老師的課程,不是所有課程)平均成績最高的學生姓名
20)查詢每門課程成績最好的前兩名學生姓名
21)查詢不同課程但成績相同的學號,課程號,成績
22)查詢沒學過“葉平”老師課程的學生姓名以及選修的課程名稱;
23)查詢所有選修了學號為1的同學選修過的一門或者多門課程的同學學號和姓名;
24)任課最多的老師中學生單科成績最高的學生姓名
mysql四-2:多表查詢