MySQL数据库查询案例分析
作者:EvanSun__
数据库的查询
简单查询
# 语法 select 字段 from 表名; 字段 * 代表查询全部 字段名 代表查询指定字段 字段名 别名 代表查询指定字段,以别名输出 distinct 字段 代表查询指定字段并去重
#1 查询所有员工所有信息 select * from emp; #2 查询全部员工姓名和工资 select ename,sal from emp; #3 查询所有员工的姓名、薪资,追加别名 select ename 别名,sal 别名 from emp; #4 查询所有职位,并去重 select distinct job from emp;
限定查询
在查询时限定某些特定的条件
# 语法 select 字段 from 表名 [限定语法]; 限定语法 where 条件(> >= < <= !=/<> or and in(元组) between...and... ...)
#1 查询薪资不等于3000的 select * from emp where sal <> 3000; #2 查询薪资大于2000,小于5000的 select * from emp where sal > 2000 and sal < 5000; select * from emp where sal between 2000 and 5000; #3 查询多张表的薪资大于1000的,为表追加别名 select * from emp e where e.sal > 2000; #4 查询名称中包含 S 的员工信息 select * from emp where ename like '%s%'; # like %s% 表示包含s的数据,通配符 % 代表匹配所有 #5 查询名称中第二个子母是 M 的员工信息 select * from emp where ename like '_m%'; # like _m% 表示包含s的数据,通配符 _ 代表匹配一个 #6 查询入职日期是 1981 的员工信息 select * from emp where hiredate like '1981%'; select * from emp where hiredate between '1981-01-01' and '1981-12-31';
排序查询
将查询后的结果作升降序排列,如果需要对多个字段进行排序,直接在排序条件后追加即可
# 语法 select 字段 from 表名 [限定语法] [排序语法]; 排序语法 关键字 order by 条件 asc(升序) desc(降序)
#1 按照入职日期做降序排列 select * from emp order by hiredate desc; #2 按照薪资做升序排列 select * from emp order by sal asc; #3 多个限定条件:按照入职日期做降序排列,如果日期相同那么根据薪资做升序排列 select * from emp order by hiredate desc,sal asc;
多表查询
如果我们要从多个表中查询数据呢,要简单的将两张表堆积在一起吗?
select * from dept,emp;
这样会带来数据冗余问题,出现多个重复数据,这种现象称之为笛卡尔效应。
# 语法 # 当两张表有关联字段时,可以通过关联字段联合查询 select 字段 from 表名1 ,表名2 where 表1_id = 表2_id;
#1 查询所有员工的员工编号、姓名、薪资、部门编号、部门名称 select e.empno 员工编号,e.ename 员工姓名,e.sal 薪资,e.deptno 部门编号,d.dname 部门名称 from emp e,dept d where e,deptno = d.deptno;
#2 查询所有员工编号、员工姓名、员工薪资、领导编号、领导姓名、领导薪资 逐步分析: # Step.1 确定需要用到的表 emp e1,emp e2 # Step.2 确定需要用到的字段 e1.empno 员工编号,e1.ename 员工姓名,e1.sal 员工薪资,e2.empno 领导编号,e2.ename 领导姓名,e2.sal 领导薪资 # Step.3 确定需要用到的关联条件 e1.mgr = e2.empno # Step.4 组装SQL select e1.empno 员工编号,e1.ename 员工姓名,e1.sal 员工薪资,e2.empno 领导编号,e2.ename 领导姓名,e2.sal 领导薪资 from emp e1,emp e2 where e1.mgr = e2.empno; # 结果发现上述查询会少一个数据,即大领导没有上司就不会满足条件,怎么办?这就需要用到后面的连接查询
所以当进行多表联接时,为了避免产生笛卡尔积,至少需要N-1个联结条件(N为表数量)
- 两表关联:需要1个条件。
- 三表关联:在前两个表的基础上,第三个表需要1个新增条件,共需2个条件。
- 依此类推,每增加一个表需新增1个条件。因此,关联n个表至少需要n-1个条件。
连接查询
# 语法: select 字段 from 表名 [连接条件][限定语法][排序条件] # 连接条件 向哪加入哪当主表,主表数据不会丢失,当主表中的某行在另一个表中没有匹配行时,则该行显示为空值(NULL);如果表之间有匹配行,则整个结果集行包含主表的数据值。 # 左(外)连接 左边当主表 left (outer) join ... on ... # 右(外)连接 右边当主表 right (outer) join ... on ... # 全连接 两边都是主表 (MySQL不支持) full join ... on ... # 内连接 全部都不是主表,只检索两个表中匹配的行 (inner) join ... on ...
#1 所以上面的例子我们可以这么优化: select e1.empno 员工编号,e1.ename 员工姓名,e1.sal 员工薪资,e2.empno 领导编号,e2.ename 领导姓名,e2.sal 领导薪资 from emp e1 left join emp e2 on e1.mgr = e2.empno;
全连接会先执行 left join 遍历左表,再执行 right join 遍历右表,最后将 right join 的结果直接追加到 left join 后面。注意,full join 会返回重复的行,它们会被保留,不会被删除。
连接语法来自于 SQL99 语法,这是1999年提出的,同时还有交叉连接(cross join)、自然连接(natural join)等,其中自然连接可以自动将两张表的相同字段提取出来放在前面,相当于自动实现多表查询
join 表 on 关联条件
join 表 using (关联字段)
分组查询
当需要分组的字段中出现了重复数据,可以使用分组查询查询有多少种类及其数量
# 语法: select 分组字段/统计函数 from 表名 [连接条件][限定语法][分组查询][排序条件] # 分组查询 group by 分组字段 # 统计函数 count(字段) 统计某一字段数量 avg(字段) 统计某一字段平均值 max(字段) 统计某一字段最大值 min(字段) 统计某一字段最小值 sum(字段) 统计某一字段的和
注意事项:
1. 一旦出现分组,那么 select 后面只允许出现分组字段及统计函数 2. 统计函数可以单独使用 3. 如果出现统计函数嵌套,那么在 select 后面只允许出现统计函数 4. 分组后如果还要使用条件判断,不允许使用 where,而是改为使用 having
#1 查询公司所有职位 select job,count(empno) from emp group by job; # 这里的分组字段是job,一般不会用count(*)扫描全表,而是用本表中的id来统计 #2 查询每个工作的平均工资 select job,count(empno),avg(sal) from emp group by job; #3 查询每个工作的平均工资 select emp.job,count(empno),avg(sal),dept.dname from emp left join dept on emp.deptno = dept.deptno group by emp.job; #4 查询平均工资高于2000的工作 select emp.job,count(empno),avg(sal),dept.dname from emp left join dept on emp.deptno = dept.deptno group by emp.job having avg(emp.sal) > 2000;
子查询
在查询中嵌套查询
# 语法 # 类型一 where子查询 # 当要查询的结果为单行单列或多行单列时 select 字段 from 表名 [where (子查询)]; # 类型二 from子查询 # 当需要将查询出来的表作为一个新表参与查询时 select 字段 from 表名,(子查询);
#1 查询比SMITH工资高的员工(单行单列) select * from emp where sal > (select sal from emp where ename = "smith"); #2 查询与销售一样薪资的员工信息(多行单列) select * from emp where sal in (select sal from emp where job = "SALESMAN"); #3 select * from emp where sal > (select avg(sal) from emp);
any 关键字
> any() 大于括号中的最小值
< any() 小于括号里的最大值
= any() 等同于 in
all关键字
> all() 大于括号中的最大值
< all() 小于括号里的最小值
= all() ???
查询部门编号、部门名称、部门位置、部门人数、平均薪资的信息
逐步分析: # Step.1 确定需要的表格 dept d,emp e # Step.2 确定需要关联的条件 d.deptno = e.deptno # Step.3 确定需要的字段 d.deptno,d.dname,d.loc,count(e.empno),avg(e.sal) # Step.4 确定需要的分组条件 group by e.deptno # Step.5 组装SQL select d.deptno,d.dname,d.loc,count(e.empno),avg(e.sal) from dept d left join emp e on d.deptno = e.deptno group by e.deptno; # 或者使用from子查询 select d.deptno,d.dname,d.loc,ifnull(temp.num,0),ifnull(temp.sal,0) from dept d left join (select d.deptno,d.dname,d.loc,count(e.empno),avg(e.sal) from dept d , emp e where d.deptno = e.deptno group by e.deptno ) temp on d.deptno = e.deptno;
分页查询
为什么需要分页 性能 页面
# 语法: select 字段 from 表名 [连接条件][限定语法][分组查询][排序条件][分页查询]; 分页查询 关键字 limit n,m n下标索引,m每页显示条数 n 默认值为0,可以省略不写,默认给出首页数据
#1 查询前十条员工信息 select * from emp limit 0,10; select * from emp limit 10;
案例一 创建菜单表,分一级菜单和二级菜单
# 自关联操作 create table t_menu( id int(5) AUTO_INCREMENT, name varchar(10), image varchar(20), url varchar(20), pid int(5), constraint pk_id primary key(id), constraint fk_pid foreign key(pid) references t_menu(id) ) # 原理:二级菜单项的pid关联一级菜单项的id,可以通过子菜单(二级菜单)的pid找到其父菜单(一级菜单)
案例二 权限管理:用户登录
# 找到当前登录的用户的功能列表 # 本案例中数据表使用之前创建的5张权限管理表 select m.mid,m.mname,m.url from t_person p left join t_person_role pr on p.pid = pr.pid left join t_role r on pr.rid = r.rid left join t_role_menu rm on r.rid = rm.rid left join t_menu m on rm.mid = m.mid;
到此这篇关于Python学习 -- MySQL数据库的查询及案例的文章就介绍到这了,更多相关mysql数据库查询内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!