VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > python入门教程 >
  • MYSQL——表相关操作(多表查询【联表查询&子查询】)

一、多表查询——多表联合查询


复制代码
# 方案1:链表查询
把多张物理表合并成一张虚拟表,再进行后续查询

#======>内链接:保留两张表有对应关系的记录
select * from emp,dep where emp.dep_id=dep.id;
select dep.name,emp.name from emp inner join dep on emp.dep_id=dep.id
    where dep.name = "技术";

#======>左链接:在内链接的基础上保留左表的记录
select * from emp left join dep on emp.dep_id=dep.id;

#======>右链接:在内链接的基础上保留右表的记录
select * from emp right join dep on emp.dep_id=dep.id;

#======>全外链接:在内链接的基础上保留左右表的记录
full join

select * from emp left join dep on emp.dep_id=dep.id
union
select * from emp right join dep on emp.dep_id=dep.id;


示例1:查询所有部门名及对应的员工个数
select dep.name,count(emp.id) from emp right join dep on emp.dep_id = dep.id
group by dep.name
;

select dep.name,count(emp.id) from emp right join dep on emp.dep_id = dep.id
group by dep.name
having count(emp.id) < 2
;

#示例2:即找出年龄大于25岁的员工以及员工所在的部门
select emp.name,dep.name from emp inner join dep on emp.dep_id = dep.id where age > 25;


#示例3:以内连接的方式查询employee和department表,并且以age字段的升序方式显示


# 把多张表链接到一起:
select * from
(select emp.*,dep.name as dep_name  from emp inner join dep on emp.dep_id = dep.id) as t1
inner join
dep
on t1.dep_id = dep.id
;

select * from emp
inner join dep
on emp.dep_id = dep.id

inner join dep as t1
on t1.id = dep.id;


# 查询部门内最新入职的员工
select * from employee
inner join
(select depart_id,max(hire_date) as maxd from employee group by depart_id) as t1
on employee.depart_id = t1.depart_id
where employee.hire_date = t1.maxd
;


复制代码

 

二、多表查询——子查询

 

复制代码
# 方案2:子查询
从一张表中查询出结果,用该结果作为查
询下一张表的过滤条件
select * from employee
where hire_date =  (select max(hire_date) from employee);


#查询平均年龄在25岁以上的部门名
select * from dep where id in
(select dep_id from emp group by dep_id having avg(age) > 25);

#查看技术部员工姓名
select * from emp where dep_id in
(select id from dep where name="技术");

#查看不足1人的部门名(子查询得到的是有人的部门id)
select * from dep where id not in (select distinct dep_id from emp);

select * from dep where exists (select * from emp where id>3);
复制代码

三、详细介绍子查询

1:子查询是将一个查询语句嵌套在另一个查询语句中。
2:内层查询语句的查询结果,可以为外层查询语句提供查询条件。
3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
4:还可以包含比较运算符:= 、 !=、> 、<等

1、in关键字的子查询
复制代码
# 1、in
select * from emp where age=18 or age=38 or age=28;
select * from emp where age in (18,38,28);

# 子查询的思路
select * from emp where dep_id in
(select id from dep where name="技术" or name="销售");

# 链表的思路
select * from emp inner join dep
on emp.dep_id = dep.id
where dep.name in ("技术","销售");


# not in不支持null
mysql> select * from dep;
+------+--------------+
| id   | name         |
+------+--------------+
|  200 | 技术         |
|  201 | 人力资源     |
|  202 | 销售         |
|  203 | 运营         |
+------+--------------+
4 rows in set (0.00 sec)
mysql> insert into emp values(7,'lili','female',48,null);
Query OK, 1 row affected (0.03 sec)

mysql> select * from emp
    -> ;
+----+------------+--------+------+--------+
| 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 | liwenzhou  | male   |   18 |    200 |
|  6 | jingliyang | female |   18 |    204 |
|  7 | lili       | female |   48 |   NULL |
+----+------------+--------+------+--------+
7 rows in set (0.00 sec)

mysql>


查询出有员工的部门,
select * from dep where id in
(select distinct dep_id from emp);

查询出没有员工的部门,
select * from dep where id not in
(select distinct dep_id from emp);


select * from dep where id not in
(select distinct dep_id from emp where dep_id is not null);
复制代码

2、any 和 all关键字的子查询

复制代码
# any后也跟子查询语句,与in不一样的地方在哪里
#   in (子查询语句)
#   in (值1,值2,值3)
#   而any只能跟子查询语句
#   any必须跟比较运算符配合使用

select * from emp where dep_id in
(select id from dep where name in ("技术","人力资源"));

select * from emp where dep_id = any
(select id from dep where name in ("技术","人力资源"));


select * from emp where dep_id not in
(select id from dep where name in ("技术","人力资源"));

select * from emp where ! (dep_id = any(select id from dep where name in ("技术","人力资源")));


查询出那些薪资比所有部门的平均薪资都高的员工=》薪资在所有部门平均线以上的狗币资本家
select * from employee where salary > all
(select avg(salary) from employee where depart_id is not null group by depart_id);

查询出那些薪资比所有部门的平均薪资都低的员工=》薪资在所有部门平均线以下的无产阶级劳苦大众
select * from employee where salary < all
(select avg(salary) from employee where depart_id is not null group by depart_id);

查询出那些薪资比任意一个部门的平均薪资高的员工=》薪资在任一部门平均线以上的员工
select * from employee where salary > any
(select avg(salary) from employee where depart_id is not null group by depart_id);


select * from employee where salary < any
(select avg(salary) from employee where depart_id is not null group by depart_id);
复制代码

3、exists关键字的子查询

ps:

 exists (子查询语句,不能用集合体)
not exists底层用索引,以提升效率
not in即便是有索引也没有用,因为他要把所有的值都走一遍

not exists 效率高于not in,因为底层用索引原因 

复制代码
# exists  对比 in
# in的效率 高于 exists
in 先把子查询语句查出结果集再应用到外层里
exists在外层取一条记录,内层子查询语句都要执行一遍,所以叫相关子查询


select * from 表1 where exists (select * from 表2);

# 例如:查询有员工的部门=》
select * from dep where exists (select * from emp where dep.id=emp.dep_id);


# not exists的效果 高于 not in
select * from dep where not exists (select * from emp where 203=emp.dep_id);



# 例:查询选修了所有课程的学生id、name:

# 实现方式一:选修了三门课程的学生就是选修了所有课程的学生
select s.id,s.name from student as s inner join student2course as sc
on s.id = sc.sid
group by sc.sid
having count(sc.cid) = (select count(id) from course);

# 实现方式二:找到这样的学生,该学生不存在没有选修过的课程
select * from student as s where not exists (
    select * from course as c not exists (
        select * from student2course as sc where sc.sid = s.id and sc.cid = c.id
    )
);


select * from student as s where not exists (
    select * from course as c where not exists (
        select * from student2course as sc where sc.sid = s.id and sc.cid = c.id
    )
);



学生记录可以过滤出来,一定是子查询内没有记录

for 学生: # s.id=2
    for 课程: # c.id=1
        for 学生2课程: # sc.sid = 2 and sc.cid = 1
            pass

==================================
for sid in [1,2,3,4]:
    for cid in [1,2,3]:
        (sid,cid)


最外层循环一次
# (1,1)
# (1,2)
# (1,3)
最外层循环二次
# (2,1)
# (2,2)
# (2,3)
最外层循环三次
# (3,1)
# (3,2)
# (3,3)
最外层循环四次
# (4,1)
# (4,2)
# (4,3)

===================================
# 例2、查询没有选择所有课程的学生,即没有全选的学生。=》找出这样的学生,存在没有选修过的课程
select * from student as s where exists (
    select * from course as c where not exists (
        select * from student2course as sc where sc.sid = s.id and sc.cid = c.id
    )
);

# 例3、查询一门课也没有选的学生=》找出这样的学生,不存在选修过的课程
select * from student as s where not exists (
    select * from course as c where exists (
        select * from student2course as sc where sc.sid = s.id and sc.cid = c.id
    )
);

# 例4、查询至少选修了一门课程的学生=》找出这样的学生,存在选修过课程
select * from student as s where exists (
    select * from course as c where exists (
        select * from student2course as sc where sc.sid = s.id and sc.cid = c.id
    )
);
复制代码

 

4、in与exists的区别

 

 

复制代码
!!!!!!当in和exists在查询效率上比较时,in查询的效率快于exists的查询效率!!!!!!

==============================exists==============================
# exists
exists后面一般都是子查询,后面的子查询被称做相关子查询(即与主语句相关),当子查询返回行数时,exists条件返回true,
否则返回false,exists是不返回列表的值的,exists只在乎括号里的数据能不能查找出来,是否存在这样的记录。

#
查询出那些班级里有学生的班级
select * from class where exists (select * from stu where stu.cid=class.id)

# exists的执行原理为:
1、依次执行外部查询:即select * from class 
2、然后为外部查询返回的每一行分别执行一次子查询:即(select * from stu where stu.cid=class.cid)
3、子查询如果返回行,则exists条件成立,条件成立则输出外部查询取出的那条记录

==============================in==============================
# in
in后跟的都是子查询,in()后面的子查询 是返回结果集的

#
查询和所有女生年龄相同的男生
select * from stu where sex='' and age in(select age from stu where sex='')

# in的执行原理为:
in()的执行次序和exists()不一样,in()的子查询会先产生结果集,
然后主查询再去结果集里去找符合要求的字段列表去.符合要求的输出,反之则不输出.
复制代码

 

 

5、带比较运算符的子查询

 

复制代码
#比较运算符:=、!=、>、>=、<、<=、<>
#查询大于所有人平均年龄的员工名与年龄
mysql> select name,age from emp where age > (select avg(age) from emp);
+---------+------+
| name | age |
+---------+------+
| alex | 48 |
| wupeiqi | 38 |
+---------+------+
2 rows in set (0.00 sec)


#查询大于部门内平均年龄的员工名、年龄
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; 
复制代码

 出处:

 https://www.cnblogs.com/guojieying/p/13629265.html

 

 


相关教程