Day055--MySQL--外键的变种,表与表的关系,单表查询,多表查询, 内连接,左右连接,全外连接

表和表的关系 ---- 外键的变种 *

一对多或多对一

多对多

一对一

如何找出两张表之间的关系

分析步骤:
#1、先站在左表的角度去找
是否左表的多条记录可以对应右表的一条记录,如果是,则证明左表的一个字段foreign key 右表一个字段(通常是id)

#2、再站在右表的角度去找
是否右表的多条记录可以对应左表的一条记录,如果是,则证明右表的一个字段foreign key 左表一个字段(通常是id)

#3、总结:
#多对一:
如果只有步骤1成立,则是左表多对一右表
如果只有步骤2成立,则是右表多对一左表

#多对多
如果步骤1和2同时成立,则证明这两张表时一个双向的多对一,即多对多,需要定义一个这两张表的关系表来专门存放二者的关系

#一对一:
如果1和2都不成立,而是左表的一条记录唯一对应右表的一条记录,反之亦然。这种情况很简单,就是在左表foreign key右表的基础上,将左表的外键字段设置成unique即可

单表查询 ***

一、单表查询的语法
   SELECT 字段1,字段2... FROM 表名
                  WHERE 条件
                  GROUP BY field
                  HAVING 筛选
                  ORDER BY field
                  LIMIT 限制条数
二、关键字的执行优先级(重点)

重点中的重点:关键字的执行优先级
from 
where       筛选
group by    分组
having      筛选, 一定用聚合
select  
distinct 去重
order by    排序
limit  限制结果显示数量
    

1.找到表:from

2.拿着where指定的约束条件,去文件/表中取出一条条记录

3.将取出的一条条记录进行分组group by,如果没有group by,则整体作为一组

4.将分组的结果进行having过滤

5.执行select

6.去重

7.将结果按条件排序:order by

8.限制结果的显示条数

where

where子句中可以使用
1.比较运算符:>、<、>=、<=、<>、!=
2.between 80 and 100 :值在80到100之间
3.in(80,90,100)值是10或20或30
4.like 'xiaomagepattern': pattern可以是%或者_。%小时任意多字符,_表示一个字符
5.逻辑运算符:在多个条件直接可以使用逻辑运算符 and or not

group by

group by 是发生在where之后,where条件是可选的

针对于相同字段进行归类

select * from employee group by post;

注意: 分组之后 ,只能获取分组的字段,如果想获取组内的信息要通过聚合函数进行计算

聚合函数

max() 最大值
min() 最小值
sum() 求和
count() 求总个数
avg() 求平均值

虚拟表

# 起别名
select A.a from (select post,count(1) as a from employee group by post) as A;

小练习

  1. 查询岗位名以及岗位包含的所有员工名字
    select post,group_concat(name) from employee group by post;
  2. 查询岗位名以及各岗位内包含的员工个数
  3. 查询公司内男员工和女员工的个数
  4. 查询岗位名以及各岗位的平均薪资
  5. 查询岗位名以及各岗位的最高薪资
  6. 查询岗位名以及各岗位的最低薪资
  7. 查询男员工与男员工的平均薪资,女员工与女员工的平均薪资

having

Mysql 5.7 整体作为一组 可以执行sql

select * from employee having salary>1000000;

Mysql 5.6 5.5

mysql>  select * from employee having salary>1000000;
ERROR 1463 (42000): Non-grouping field 'salary' is used in HAVING clause
# 必须分组之后才能使用having

各组内平均年龄大于25岁的人数,平均年龄

select count(1),avg(age),post from employee group by post having avg(age) > 25;

select post, count(1),group_concat(name) from (select name, age, post from employee where post in 
(select post as age_a from employee group by post having avg(age) > 25) and age >25) as n_a_p group by post;

分组和having练习

1. 查询各岗位内包含的员工个数小于2的岗位名、岗位内包含员工名字、个数
2. 查询各岗位平均薪资大于10000的岗位名、平均工资
3. 查询各岗位平均薪资大于10000且小于20000的岗位名、平均工资

select post,group_concat(name),count(1) from employee group by post having count(1) < 2;

select post,avg(salary) from employee group by post having avg(salary) > 10000;


select post,avg(salary)  from employee group by post having avg(salary) > 10000 and avg(salary) < 20000;

order by

#先根据年龄进行升序 再根据id进行降序
select * from employee order by age asc, id desc;



2. 查询各岗位平均薪资大于10000的岗位名、平均工资,结果按平均薪资降序排列

select post,avg(salary) as a from employee group by post having avg(salary) > 10000 order by a desc;

limit 限制

# 分页 分页不是这么简单
select * from employee limit 0,5;
select * from employee limit 5,5;
select * from employee limit 10,5;

多表查询 **

多表连接查询

笛卡尔积





# 符合条件查询
select  * from employee,department where employee.dep_id = department.id;

内连接

只获取匹配的数据

select * from employee inner join department on employee.dep_id = department.id;

左连接 或右连接

只显示左表所有记录

select * from employee left join department on employee.dep_id = department.id;

全外连接

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;

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;

#注意 union与union all的区别:union会去掉相同的纪录

练习题

1.即找出年龄大于25岁的员工以及员工所在的部门

select department.name, employee.name,employee.age from employee left join department on employee.dep_id = department.id where age >25;  # xiaomage部门null

select department.name, employee.name,employee.age from employee inner join department on employee.dep_id = department.id where age >25;  # 不包含没有部门的人

子查询

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

小练习

#查询平均年龄在25岁以上的部门名
select * from department where id in (select dep_id from employee group by dep_id having avg(age) > 25);
# 查看技术部员工姓名

#查看不足1人的部门名


# 查询大于部门内平均年龄的员工名、年龄
select name,age from employee inner join (select dep_id,avg(age) as av from employee group by dep_id) as B on employee.dep_id = B.dep_id where age > av;

猜你喜欢

转载自www.cnblogs.com/surasun/p/10009550.html