1. 程式人生 > >mysql四-2:多表查詢

mysql四-2:多表查詢

多表查詢 mysql 51cto

一、準備表

新建表

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:多表查詢