day46 记录/数据的增删改, 查询数据/记录(单表查询、多表查询),子查询

中括号内的可写也可以不写。
mysql 最核心的就是数据查询语句 ,所以 今天都必须掌握。
1.表的增删改查

2.单表查询

  select查询语句的完整写法 = 关键字的书写顺序
  关键字的执行顺序

3.多表查询
笛卡尔积
内连接
左外连接
右外连接
全外连接:就是通过合并左外连接和右外连接。

4.子查询
一个查询包含另一个查询 被包含的叫子查询
当一个查询的结果 是另一个查询的条件时 ,这个查询叫子查询。
子查询需要用括号包起来。

 


 

一。表的增删改
  增加
insert [into] 表名[(可选字段名)] values(一堆值1),(一堆值2),.....
注意:1.into 可以省略;
     2.表名后的字段可以选,
如果写了 后面的values中的值必须与表名后的字段一一对应;
如果没写 后面的values中的值必须与表的所有字段一一对应。
     3.values后面可以给一组数据值 或者 多组数据值 用逗号隔开。

  删除
delete from 表名[where 条件]
条件不写时, 是删除所有记录, 是一行一行删除 注意:这样的删除自增主键id 不会归零。
truncate 重建表: 先记录表结构, 删除整个表再重新建出来表, 自增主键id 会归零。     -----------运用??

  更新数据
update 表名 set 字段名 = 值[,字段2 = 值2],[where 条件]
可以一次性修改多个字段的值用逗号隔开
条件如果不写, 修改所有记录。

二.单表查询
简单查询:不带关键字的查询。语法如下:
select {1.*/2.字段名/3.四则运算/4.聚合函数} from 表名 

select义查询
1.* 表示查询所有字段;
2.可以手动要查询的字段
3.字段的值可以进行加减乘除运算;
4.聚合函数,用于统计;
5.where 是可选的。


数据准备
create table stu(id int primary key auto_increment,name
char(10),math float,english float);
insert into stu values(null,"赵云",90,30);
insert into stu values(null,"小乔",90,60);
insert into stu values(null,"小乔",90,60);
insert into stu values(null,"大乔",10,70);
insert into stu values(null,"李清照",100,100);
insert into stu values(null,"铁拐李",20,55);
insert into stu values(null,"小李子",20,55);

 

完整的select 语句 语法 *****=关键字的书写顺序如下:
select [distinct] * from 表名
[where +条件
group by +字段
having +条件
order by
limit
]


关键字的作用:
distinct 去除重复数据:所有数据全都重复才算重复。
where 在逐行读取数据时的一个判断条件。
group by 对数据分组。
having 对分组后的数据进行过滤。
order by 对结果排序。
limit 指定获取数据记录的条数。


注意: 在书写时,必须按照这个顺序来写,但是书写顺序不代表执行顺序。

 

数据库伪代码
def from():
打开文件
def where():
对读取的数据进行过滤

def group_by():
对数据分组
def having():
对分组后的数据进行过滤
def distinct():
去除重复数据
def order():
排序
def limit():
指定获取条数

 

select 关键字的执行顺序 *****
def select(sql):
data = from()
data = where(data)
data = group by(data)
data = having(data)
data = distinct(data)
data = orderby(data)
data = limit(data)
return data;

简单查询
指定显示格式:
concat()函数:用于拼接字符串。   ??
select
(
case
when english + math > 120 then
concat(name," nice")
when english + math <= 130 then
concat(name," shit")
end
) ,english,math from stu; *完全不重要

where 条件


create table emp (id int,name char(10),sex char,dept char(10),jobchar(10),salary double);

insert into emp values
(1,"刘备","男","市场","总监",5800),
(2,"张飞","男","市场","员工",3000),
(3,"关羽","男","市场","员工",4000),
(4,"孙权","男","行政","总监",6000),
(5,"周瑜","男","行政","员工",5000),
(6,"小乔","女","行政","员工",4000),
(7,"曹操","男","财务","总监",10000),
(8,"司马懿","男","财务","员工",6000);

 


 

group by 分组查询 *****
  什么是分组?
把一个字段作为分组依据,把一个整体 分割为多个部分。
  为什么分组?
在数据库中分组为了易于统计 *****

了解:
在mysql 5.6中 分组后会默认显示 每组的第一条记录 ,但这是没有意义的;
5.7不显示 因为5.7中 sql_mode中自带 ONLY_FULL_GROUP_BY(义只有分组的字段数据可显示)。

语法:select *from emp group by dept;

group by 后面可以有多个分组与依据 ,会按照从左到右顺序依次执行。

 

分组后的特点:1.组里的详细记录就被隐藏起来了 ,不能直接查看。
eg:dept 一分组 变成三条记录 每个组中却包含多条记录 没办法显示
2.一定要显示的话:可以使用group_concat(字段名),它可以将多个值拼接成一个字符串。

注意*****: 1.只有出现在group by 后面的字段 才可以被显示,其他都被隐藏了
 3.可以通过聚合函数统计,来显示组内记录的统计结果。

注意:聚合函数不能写在where的后面 where最先执行 它的作用是从硬盘读取数据并过滤 ,以为数据还没有读取完 ,所以此时不能进行统计。

sum作用:求数据的和。       avg:求数据的平均数。

count作用:统计字段下的数据个数。      max/min:求数据的最大值最小值。

示例:
    SELECT COUNT(*) FROM employee;
    SELECT COUNT(*) FROM employee WHERE depart_id=1;
    SELECT MAX(salary) FROM employee;
    SELECT MIN(salary) FROM employee;
    SELECT AVG(salary) FROM employee;
    SELECT SUM(salary) FROM employee;
    SELECT SUM(salary) FROM employee WHERE depart_id=3;

 

 什么样的字段适合用于分组?

重复性高的字段

eg:请查询每种性别的平均工资
性别分组
请查询每种岗位的平均工资
岗位分组
小窍门:每后面就是分组的依据。

 


 

 

HAVING

常用于分组后的筛选

但是having和where不一样的地方在于以下几点!!!

复制代码
#!!!执行优先级从高到低:where > group by > 聚合函数 > having >order by
1.where和having的区别                                                                                
     1. Where 是一个约束声明,使用Where约束来自数据库的数据,Where是在结果返回之前起作用的                                        
     (先找到表,按照where的约束条件,从表(文件)中取出数据),Where中不能使用聚合函数                                              
     2.Having是一个过滤声明,是在查询返回结果集以后对查询结果进行的过滤操作                                                     
     (先找到表,按照where的约束条件,从表(文件)中取出数据,然后group by分组,                                                
      如果没有group by则所有记录整体为一组,然后执行聚合函数,然后使用having对聚合的结果进行过滤),                                     
      在Having中可以使用聚合函数。                                                                          
     3.where的优先级比having的优先级高                                                                     
     4.having可以放到group by之后,而where只能放到group by 之前。 

 

验证不同之处:
1.查看员工的id>15的有多少个 select count(id) from employee where id>15;#正确,分析:where先执行,后执行聚合count(id), 然后select出结果 select count(id) from employee having id>15; #报错,分析:先执行聚合count(id),后执行having过滤, #无法对id进行id>15的过滤 #以上两条sql的顺序是 1:找到表employee--->用where过滤---->没有分组则默认一组执行聚合count(id)--->select执行查看组内id数目 2:找到表employee--->没有分组则默认一组执行聚合count(id)---->having 基于上一步聚合的结果(此时只有count(id)字段了) 进行id>15的过滤,很明显,根本无法获取到id字段

 

 


 

order by 排序用的
asc 表示升序 是默认的
desc 表示降序
by 后面可以有多个排序依据

limit 限制显示条数

limit a,b
limit 1,5
从1开始 到5结束 错误
含义是:从1开始 不包含1,取5条记录。

分页查询
每页显示3条 共有10条数据
if 10 % 3 == 0:
10 / 3
else:
10/3 +1
总页数4

第一页
select *from emp limit(0,3)
第二页
select *from emp limit(3,3)
第二页
select *from emp limit(6,3)

起始位置的算法
页数 - 1 * 条数
1 - 1 = 0 * 3 = 0
2 - 1 = 1 * 3 = 3


三。正表达式匹配
由于like只能使用% 和 _ 不太灵活,
可以将like换为 regexp 来使用正则表达式。

 


 

四。多表查询 ******
数据准备
create table emp (id int,name
char(10),sex char,dept_id int);
insert emp values(1,"大黄","m",1);
insert emp values(2,"老王","m",2);
insert emp values(3,"老李","w",30);

create table dept (id int,name char(10));
insert dept values(1,"市场");
insert dept values(2,"财务");
insert dept values(3,"行政");

1.交叉连接查询、笛卡尔积查询
  select *from 表1,表n
查询结果是:左表中的每条记录 与右表中的每条记录都关联一遍。
因为 他不知道什么样的对应关系是正确 只能帮你都对一遍。
a表有m条记录 b表有n条记录,笛卡尔积结果为m * n 记录。

需要自己筛选出正确的关联关系
  select *from emp,dept where emp.dept_id = dept.id;

2.内连接查询 就是笛卡尔积查询
  select *from emp [inner] join dept;等同于select *from 表1,表n。
  select *from emp inner join dept where emp.dept_id = dept.id;

3.左外连接查询
select *from emp left join dept on emp.dept_id = dept.id;
左表数据全部显示 右表只显示匹配上的

4.右外连接查询
select *from emp right join dept on emp.dept_id = dept.id;
右表数据全部显示 左表只显示匹配上的

内和外的理解 内指的是匹配上的数据 外指的是没匹配上的数据

5.全外连接
select *from emp full join dept on emp.dept_id = dept.id; ##mysql不支持

union 合并查询结果
select *from emp left join dept on emp.dept_id = dept.id
union
select *from emp right join dept on emp.dept_id = dept.id;

union 去除重复数据 只能合并字段数量相同的表
union all 不会去除重复数据


on 关键字 where 都是用于条件过滤 没有本质区别
在单表中where的作用是筛选过滤条件
在多表中where 连接多表 满足条件就连接 不满足就不连接
为了区分是单表还是多表 搞个新的名字 就是 on
只要是连接多表的条件 就使用on


三表查询

 

 

create table stu(id int primary key auto_increment,name char(10));
create table tea(id int primary key auto_increment,name char(10));
create table tsr(id int primary key auto_increment,t_id int,s_id int,
foreign key(s_id) references stu(id),
foreign key(s_id) references stu(id));
insert into stu values(null,"张三"),(null,"李李四");
insert into tea values(null,"egon"),(null,"wer");
insert into tsr values(null,1,1),(null,1,2),(null,2,2);

select *from stu join tea join tsr
on stu.id = tsr.s_id and tea.id = tsr.t_id
where tea.name = "egon";


记:多表查询套路:******
1.把所有表都连接起来;
2.加上连接条件;
3.如果有别的过滤条件,加上where。

 

5.子查询

什么是子查询?
条件当一个查询a的结果是另一个查询b的条件时, 这个查询a称之为子查询(内层查询)。

什么时候使用子查询?
当一次查询无法得到想要结果时 需要多次查询。多表连接查询可分解为多步子查询!!。

 

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

 

 

记:子查询解决查询问题的思路:******
是把一个复杂的问题 拆分为多个简单的问题,
是把一个复杂的查询 拆分为多个简单的查询。
in (1,2)

给你部门的的名称
查部门有哪些人?
第一步查到部门的id
第二部 拿着id去员工表查询
select *from dept join emp on dept.id = emp.dept_id;

select *from emp join
# 使用子查询 得到 每个部门的id 以及部门的 最高工资 形成一个虚拟表 把原始表和 虚拟表连接在一起
(select dept_id,max(salary)as m from emp group by dept_id) as t1
# 如果这个人的部门编号 等于 虚拟表中的部门编号
on emp.dept_id = t1.dept_id
and
# 并且 如果这个人的工资 等于 虚拟表中的最高工资 就是你要找的人
emp.salary = t1.m;

 

posted @ 2018-11-22 16:29  timm_book  阅读(111)  评论(0)    收藏  举报