MySQL表单的查询及分组聚合整理

1|0单表查询

1|11.表与表关系

1|01.1校区表 班级表 一对多

​ 校区表 一个校区可以有多个班级 一对多
​ 班级表 一个班级可不可以对应多个校区
​ 校区表 校区id 校区名称 校区城市 校区地址
​ 班级表 班级id 班级名称 开班日期 班主任 校区id
​ 多(foreign key)关联一这张表
​ 班级表创建foreign key关联校区表的校区id字段

1|01.2学生表 班级表 多对多

​ 站在学生的角度上 一个学生属于多个班级 一对多
​ 站在班级的角度上 一个班级可以有多个学生么 多对一
​ 学生表 学生id 学生姓名 ...
​ 班级表 班级id 班级名称 ...
​ 产生第三张表
​ 一个字段是外键关联另一个表的主键
​ 另一个字段外键关联另一张表的主键

1|01.3学生表 客户表 一对一

​ 一个客户对应一个学生
​ 学生表gid foreign key 关联客户表id主键
​ 并且gid还要设置为unique

1|22.单表查询

1|02.1有关查看的语句

select user(); # 查看当前用户 select database(); # 查看当前数据库 select now(); # 查看当前时间

1|02.2查看的基本语法

# select *(全部) from 表名; select * from t1; # select 字段名 from 表名; select name from t1: # select 字段名,字段名,字段名 from 表名; select name, age from t1;

1|02.3distinct(去重)

# select distinct 字段 from 表; select distinct name from t1; # 对查出来的字段进行去重

1|02.4查询能进行四则运算

# select emp_name,salary*12 from 表 select emp_name,salary*12 from t1 # 字段salary参与了四则运算

1|02.5concat

对字段进行加工

# select concat(字段,'字符串1',字段) from 表 select concat(emp_name,' : ',salary) from employee; # 如果按照上面的写法,加工后的字段名就会变为concat(emp_name,' : ',salary),很难看 select concat(emp_name,' : ',salary) as info from employee; select concat(emp_name,' : ',salary) info from employee; # 上面的两种写法效果相同,将字段名变为info # 加工后的效果为------>姓名:工资

1|02.6concat_ws

# select concat_ws('分隔符',字符串,字段1,字段2) info from employee; select concat_ws('|','信息',emp_name,salary) info from employee; # 使用分隔符将信息分隔开,可以加入字符串进行辅助拼接 # 与concat类似可以修改字段名

1|02.7case

select( case # 语句头,相当于begin when emp_name = 'alex' then # when 条件 then concat(emp_name,'BIGSB') # 输出查询的字段,可加工 when emp_name = 'jingliyang' then emp_name else # 最后一条写else concat(emp_name,'sb') end # 语句尾 ) as new_name # 字段重命名 from employee;

1|02.8where筛选行

select * from 表 where 条件

1|02.8.1范围查询

①>大于

select age from t1 where age > 20;

②<小于

select age from t1 where age < 20;

③>=大于等于

select age from t1 where age >= 20;

④<=小于

select age from t1 where age <= 20;

⑤=等于

select age from t1 where age = 20;

⑥!=或<>不等于

select age from t1 where age != 20; # 或 select age from t1 where age <> 20;

1|02.8.2模糊查询

①like:

Ⅰ. % 一个百分号代表任意长度的任意字符

# 'a%' 判断以a开头 select name from t1 where name like 'a%'; # '%ing' 判断以ing结尾 select name from t1 where name like '%ing'; # '%a%' 判断存在a select name from t1 where name like '%a%';

Ⅱ. _ 一个下划线代表一个任意字符

# 'a__' 判断以a开头的三个字符 select name from t1 where name like 'a__';

②regexp

实际上就是进行正则运算

# '^a' 判断以a开头 select name from t1 where name regexp '^a'; # 'a$'判断以a结尾 select name from t1 where name regexp 'a$';

1|02.8.3 is与is not

# 数据库中不能使用=去判断null,因此提供了is与is not 去判断null select name from t1 where name is null; select name from t1 where name is not null;

1|02.8.4逻辑运算

# and select name from t1 where name='alex' and age = 18; # or select name from t1 where name='alex' or name = 'sb'; # not select name from t1 where not age > 30;

1|33.表的修改

# alter table 表名 rename 新表名; alter table t1 rename t2; # alter table 表名 add 新字段 类型(宽度) 约束; alter table t2 add post char(12) not null; # add 新字段 类型(宽度) 约束 after id alter table t2 add post char(12) not null after id; # 插在id之后 # add 新字段 类型(宽度) 约束 first alter table t2 add post char(12) not null first; # 排头 # alter table 表名 drop 字段名; alter table t1 drop post; # alter table 表名 change 旧字段 新字段 类型(宽度) 约束; alter table t1 change name new_name char(20) not null; alter table t1 change name name char(12) null;# 使name可以为空 # alter table 表名 modify 存在的字段 新类型(新宽度) 新约束; alter table t1 modify name char(12) unique; alter table t1 modify name char(12) unique after id;

1|44.数据操作补充

# 增加 # insert into 表名 value (1,'alex','female') 使用value一次只能增加一条记录 insert into t1 value (1, 'alex', 'female'); # insert into 表名 values (1,'alex','female'),(1,'alex','female'); insert into t1 values (1, 'alex', 'female'),(2, 'alex', 'female') # insert into 表名(name,gender) values ('alex','female'); *****常用 insert into t1(name, gender) values ('alex', 'female'),('alexsb', 'female'); # insert into 表名(name,gender) select (username,sex) from 表2; insert into t1(name, gender) select (username, sex) from t2; # 修改 # update 表名 set 字段=值1 where 条件 update t1 set age=18 where age > 18; # update 表名 set 字段1=值1,字段2=值2 where 条件 update t1 set age=18, sex='女' where age > 18 and sex='男';

2|0数据库中的分组与聚合

2|11.数据库中关键字的执行顺序

①select 想要的列 from 表
②where 先从这张表中查询的行
③group by 分组
④having 对组过滤
⑤order by 排序
⑥limit 取一个区间

2|22.分组(group by)

使用情况:

根据某个重复率比较高的字段进行的,
这个字段有多少种可能就分成多少个组

功能:

①分组
②去重
注:一旦分组了就不能对具体某一条数据进行操作了

数据表:

# 使用group by select * from employee group by post;

使用group by 时会出现一些问题:

这里引出group_concat()

select group_concat(emp_name) from employee where post='teacher' group by post;

2|33.聚合(count,max,min,sum,avg)

聚合:

99.99%的情况都是和分组一起用的
如果没有和分组一起用,默认一整张表是一组

# count(id) / count(*) 计数 :每个组对应几条数据 select count(id) from employee; # max 求最大值: 这个组中某字段的最大值 select max(hire_date) from employee; # min 求最大值: 这个组中某字段的最小值 select min(hire_date) from employee; # avg 求平均值 select avg(salary) from employee; # sum 求和值 select sum(salary) from employee;

2|44.过滤(having)

# 就是一个对组进行筛选的条件 # 要部门人数大于3个人的部门 count(id)>3 select post from employee group by post having count(id)>3;

2|55.排序(order by)

# order by 字段(升序) select emp_name,age from employee order by age; # order by 字段 asc(升序) select emp_name,age from employee order by age asc; # order by 字段 desc(降序) select emp_name,age from employee order by age desc; # order by 字段1,字段2(对字段1升序,然后在字段1的基础下对字段2升序) select emp_name,age from employee order by age,salary; # order by 字段 asc,字段2 desc(对字段1升序,然后在字段1的基础下对字段2降序) select emp_name,age from employee order by age asc,salary desc; # order by 字段 desc,字段2 asc(对字段1降序,然后在字段1的基础下对字段2升序) select emp_name,age from employee order by age desc,salary asc; # order by 字段 desc,字段2 desc(对字段1降序,然后在字段1的基础下对字段2降序) select emp_name,age from employee order by age desc,salary desc;

2|66.限制(limit)

limit的用途:

①显示分页

# limit m,n # 若写为limit n,默认m为0 # 表示从m+1开始,取n条 # limit 0,6 表示从1开始取6条 # limit 6,6 表示从7开始取6条 # limit 12,6 表示从13开始取6条 # limit 18,6 表示从19开始取6条 # 只显示一条信息 select emp_name,age from employee limit 1; select emp_name,age from employee limit 0,1;# (两条效果相同) ################################################################ # 有时面试中面试官会问 limit offset的用法,你会懵逼! # limit n offset m :从m+1开始,取n条 (*******************************) limit 1 offset 0; 与 limit 0,1; limit 1; 完全一样!!!!!

②取前n名

# 跟order by一起用 # 取最小年龄 select emp_name,age from employee order by age limit 1;

7.使用python操作数据库

注:你的python中有pymysql模块

import pymysql conn = pymysql.Connection(host='127.0.0.1', user='root', password="123",database='db1') # 相当于socket里面的conn cur = conn.cursor() # 记住 lst = ['学python从开始到放弃|alex|人民大学出版社|50|2018-7-1', '学mysql从开始到放弃|egon|机械工业出版社|60|2018-6-3', '学html从开始到放弃|alex|机械工业出版社|20|2018-4-1', '学css从开始到放弃|wusir|机械工业出版社|120|2018-5-2', '学js从开始到放弃|wusir|机械工业出版社|100|2018-7-30'] sql = 'insert into book values(%s,%s,%s,%s,%s)' # 格式化 for i in lst: cur.execute(sql, (i.split('|'))) # 后面传参要用可迭代对象 conn.commit() # 将数据提交至数据库写入 cur.close() # 关闭 conn.close() # 关闭

3|0多表查询

3|11.连表查询前的序曲

1|01.1数据准备

#建表 create table department( id int, name varchar(20) ); 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 ); #插入数据 insert into department values (200,'技术'), (201,'人力资源'), (202,'销售'), (203,'运营'); 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) ;

1|01.2笛卡尔积

先计算两张表的笛卡尔积,再根据用户给出的条件进行筛选

# 连表 select * from employee,department;

因此我们可以使用where来进行筛选:

select * from employee,department where dep_id = department.id;

但是这里也会存在问题,我们这里通过where来进行连表操作,导致where字段被占用了,无法对后续的记录进行筛选.因此这个连表操作是错误的!

3|22.连表操作

概念:原来是两张表,现在拼成一张表,所有的操作都像是操作一张表一样了

1|02.1内连接

# 内连接 inner join ... on 连接条件 # select * from 表1 inner join 表2 on 条件 select * from employee inner join department on dep_id = department.id; # employee --> dep_id: 200,201,202,204 # department --> id : 200,201,202,203 # 内连接 :只显示两张表中互相匹配的项,其他不匹配的不显示

1|02.2外链接

1|02.2.1左外连接

# 左外连接 left join .. on # select * from 表1 left join 表2 on 条件 select * from employee left join department on dep_id = department.id; # 不管左表中是不是匹配上都会显示所有内容
select * from department left join employee on dep_id = department.id; # 不管左表中是不是匹配上都会显示所有内容

1|02.2.2右外链接

# 右外连接 right join .. on # select * from 表1 right join 表2 on 条件 select * from employee right join department on dep_id = department.id; # 不管右表中是不是匹配上都会显示所有内容

1|02.2.3全外链接

mysql不支持full join 的写法,但是可通过union来实现全外连接

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

3|33.子查询

1|03.1概念

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

1|03.2实例

in:

# 存在年龄大于25岁员工的部门 select distinct dep_id from employee where age>25; # 查询年龄大于25的员工的部门id并去重 select * from department where id in (select distinct dep_id from employee where age>25); # 使用in 去筛选

exists:

select * from employee where exists (select id from department where id=200); # 使用EXISTS关键字时,内层查询语句不返回查询的记录,而是返回一个真假值,True或False # 当返回True时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询.

3|44.连表查询与子查询

问题a:

# a.查询平均年龄在25岁以上的部门名 # 第一步:求部门的平均年龄>25岁的 部门id select dep_id from employee group by dep_id having avg(age)>25; # 第二步:构建子查询根据部门id求部门名 select name from department where id in (select dep_id from employee group by dep_id having avg(age)>25);

问题b:

# b.查询平均年龄在25岁以上的部门名,平均年龄的值 # 方法1: # 第一步:先查部门的平均年龄>25岁的部门id,平均年龄 select dep_id,avg(age) from employee group by dep_id having avg(age) > 25; # 第二步:查出结果在之后再连表 select name,avg_age from department as d right join (select dep_id,avg(age) as avg_age from employee group by dep_id having avg(age) > 25) as t on d.id = t.dep_id;

总结:

①如果最终需要的结果只出现在一张表中,可以用子查询解决问题
②如果最终需要的结果出现在两个表中,那么最后用的一定是连表查询

3|55.补充select的用法

select还能这么使用:

数据准备:

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 ); 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) ;

实例:

# 求每个部门最早入职的员工姓名 select (select t2.name from employee as t2 where t2.post=t1.post order by hire_date desc limit 1) from employee as t1 group by post;

__EOF__

本文作者CoderI
本文链接https://www.cnblogs.com/CoderI/p/12743101.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   CoderI  阅读(544)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示