SQL语句查询关键字:where筛选、group by分组、distinc去重、order by排序、limit分页()

  • SQL语句查询关键字
  • 前期数据准备
  • 编写SQL语句的小技巧
  • 查询关键字之where筛选
  • 查询关键字之group by分组
  • 查询关键字之having过滤
  • 查询关键字值distinct去重
  • 查询关键字值order by排序
  • 查询关键字之limit分页
  • 查询关键字之regexp正则表达式
  • 多表查询的思路

SQL语句查询关键字

select
	指定需要查询的字段信息
	select *		查所有字段
	select name		查name字段
	select char_length(name)	支持对字段做处理

from
	指定需要查询的表信息
	from mysql.user
	from t1
	
SQL语句中关键字的执行和编写顺序并不是一致的 可能会错乱
eg:
	select id,name from userinfo;
	我们先写的select在写的from 但是执行的时候是先执行的from再执行select
	
对应关键字的编写顺序和执行顺序没有过多地在意 熟练之后会非常自然的编写 只需要把注意力放在每个关键字的功能上即可

前期数据准备

create table emp(
	id int primary key auto_increment,
    name varchar(32) not null,
    gender enum('male', 'female') not null default 'male'	# 大部分是男的
    age int(3) unsigned not null default 28,
    hire_date date not null,
    post varchar(64),
    post_comment varchar(64),
    salary double(15,2),
    office int,
    depart_id int
);

# 插入记录
insert into emp(name,gender,age,hire_data,post,salary,office,depart_id) values
('jason','male',18,'20170301','浦东第一帅形象代言',7300.33,401,1), #以下是教学部
('tom','male',78,'20150302','teacher',1000000.31,401,1),
('kevin','male',81,'20130305','teacher',8300,401,1),
('tony','male',73,'20140701','teacher',3500,401,1),
('owen','male',28,'20121101','teacher',2100,401,1),
('jack','female',18,'20110211','teacher',9000,401,1),
('jenny','male',18,'19000301','teacher',30000,401,1),
('sank','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);


create table emp(
	id int primary key auto_increment,
	name varchar(16) not null,
    gender enum('male','female') not null default 'male',
    age int(3) unsigned not null default 18,
    hire_date date not null,
    post varchar(64),
    past_comment varchar(100),
    salary double(15,2),
    office int,
    depart_id int

编写SQL语句的小技巧

针对select后面的字段名可以先用*号占位往后写 最后再回来修改

在实际应用中select后面很少直接写*号 因为*号表示所有 当表中字段和数据都特别多的情况下非常浪费数据库资源

'''
SQL语句的编写类似于代码的编写 不是一蹴而就的 也需要反反复复的修修补补
'''

查询关键字之where筛选

  • 查询id大于等于3小于6的数据
select * from emp where id >= 3 and id <= 6;  # 支持逻辑运算符

select * from emp where id bewteen 3 and 6;

  • 查询薪资是20000或者18000或者17000的数据
select * from emp where salary=20000 or salary=18000 or salary=17000;

select * from emp where salary in (20000,18000,17000);  # 支持成员运算
  • 查询id小于3大于6的数据
select * from emp where id<3 or id>6;

select * from emp where id not between 3 and 6;
  • 查询员工姓名中包含字母o的员工姓名与薪资
select * from emp where name like '%o%';

条件不够精确的查询 称之为 模糊查询
模糊查询的关键字是:	like
迷糊查询的常用符号:
%	# 通配符代表零个 一个或多个字符 匹配任意个数的任意字符
eg:
	%o%		o jason owen loo wwoww	匹配所有带o字符与的
	%o		o asdasdo asdo 匹配以o结尾的字符
	
_	# 匹配单个个数的任意字符
eg:
	_o_		aox wob iok
	o_		oi ok ol	
  • 查询员工姓名是由字符组成的员工姓名与其薪资
select * from emp where name like '____';

select * from emp where char_length(name)=4;
  • 查询岗位描述为空的员工名与岗位名 针对null不能用等号 只能用is
select * from emp where post_comment=NULL;	错误不可以
select * from emp where post_comment is NULL;  可以

在MySQL中也有很多的内置方法 我们可以通过查看帮助手册学习 help 方法名

查询关键字之group by分组

分组:按照指定的条件将单个单个的数据组成一个个整体

如:将班级学生按照指定性别分组

将全国人民按照名族分组

将全世界的按照肤色分组

分组的目的是为了更好的统计相关数据

如:每个班级的男女比例

每个人民族的总占比

每个部门的平均薪资

聚合函数

max:最大值 min:最小值 sum:求和 avg:平均值 count:计数

  • 将员工数据按照部门分组
select * from emp group by post;

'''
MySQL5.6默认不会报错
	set global sql_mode='strict_tran_tables,only_full_group_by'
	
MySQL5.7及8.0默认都是会报错的
	原因是分组之后 select后面默认只能填写分组的依据 不能再写其他字段
	select post from emp group by post;
	select age from emp group by age;
	分组之后默认的是最小单位就应该是组 而不应该再是组内的单个数据单个字段
'''
  • 获取每个部门的最高工资
# 要不要 分组我们完全可以从题目中的需求中分析出来尤其是出现的关键字 每个 平均

select post,max(salary) from emp group by post;

针对sql语句执行之后的结果 我们是可以修改字段名称的 关键字as 也可以省略
select post as '部门',max(salary) as '最高薪资' from emp group by post;
  • 一次获取部门薪资相关统计
select post,max(salary) '最高薪资',min(salary) '最低薪资',avg(salary) '平均工资',sum(salary) '月支出' from emp group by post;
  • 统计每个部门的人数
select post,count(id) from emp group by post;
  • 统计每个部门名称以及部门下的员工姓名
# 分组以外的字段无法直接填写 需要借助于方法
select post,name from emp group by post;
select post,group_concat(name) from emp group by post;
select post,group_concat(name,age) from emp group by post;

select post,group_concat(name,'|',age) from emp group by post;
select post,group_concat(name,'_NB') from emp group by post;
select post,group_concat('DSB_',name,'_NB') from emp group by post;

查询关键字之having过滤

having与where本质是一样的 都是用来当对数据做筛选

只不过where用在分组之前(首次筛选)

having用在分组之后(二次筛选)

  • 统计各部门年龄在30岁以上的员工平均工资 并且保留大于10000的数据
对于复杂的点的SQL 跟写代码几乎一样 也是需要提前想好大致思路

# 没一条的结果可以直接看成就是一张表 基于该表如果还想继续操作则直接在生产该表的SQL语句上添加即可

NO1.先筛选出所有年龄大于30岁的员工数据
	select * from emp where age > 30;
NO2.再对筛选出来的数据按照部门分组并统计平均薪资
	select post,avg(salary) from emp where age > 30 group by post;
NO3.针对分组统计之后的结果再做筛选
	select post,avg(salary) from emp where age > 30 group by post having avg(salary) > 10000;

查询关键字值distinct去重

去重有一个必须的条件也是很容易被忽略的条件 数据必须是一模一样才可以去重

select distinct id,age from emp;  关键字针对的得是多个字段组合的结果
select distinct age from emp;
select distinct age,post from emp;

查询关键字值order by排序

  • 可以是单个字段排序
1.可以是单个字段排序
select * from emp order by age;  默认升序
select * from emp order by age asc;  默认升序(asc可以省略)

select * from emp order by age desc;  降序
  • 也可以是多个字段排序
select * from emp order by age,salary desc;  # 先按照年龄升序排 相同的情况下就再按照薪资降序排

统计各部年龄在10岁以上的员工平均工资 并且保留平均工资大于1000的部门 然后对平均工资进行排序

1.先筛选出所有年龄大于10岁的员工
select * from emp where age > 10;

2.再对他们按照部门分组统计平均薪资
select post,avg(salaey) from emp where age > 10 group by post;

3.针对分组的结果二次筛选
select post,avg(salary) from emp where age > 10 group by post having avg(salary)>1000;

4.最后按照指定字段排序
select post,avg(salary) from emp where age > 10 group by post having avg(salary)>1000 order by avg(salary);

'''
当一条SQL语句中很多都需要使用聚合函数计算之后的结果 可以节省操作(主要是节省的底层的运行效率 代码看不出来)
select post,avg(salary) as avg_salary from emp where age > 10 group by post having avg_salary>1000 order by avg_salary;

'''

查询关键字之limit分页

当表中数据特别多的情况下 很少会一次性获取所有的数据 很多网站也是做了分页处理一次性只能看一点点

select * from emp limit 5; 直接限制展示的条数
select * from emp limit 5,5; 从第5条开始往后读取5条

查询工资最高的人的详细信息

# 不要惯性思维 一看到工资就想着用分组聚合

select * from emp order by salary decs limit 1;

查询关键字之regexp正则表达式

SQL语句的模糊匹配如果不习惯 可以自己写正则批量查询
select * from emp where name regexp '^j.*?(n|y)$';

多表查询的思路

数据

表数据准备
create table dep(
  id int primary key auto_increment,
  name varchar(20) 
);

create table emp(
  id int primary key auto_increment,
  name varchar(20),
  sex enum('male','female') not null default 'male',
  age int,
  dep_id int
);

#插入数据
insert into dep values
(200,'技术'),
(201,'人力资源'),
(202,'销售'),
(203,'运营'),
(205,'财务');
insert into emp(name,sex,age,dep_id) values
('jason','male',18,200),
('dragon','female',48,201),
('kevin','male',18,201),
('nick','male',28,202),
('owen','male',18,203),
('jerry','female',18,204);

select * from emp,dep;

会将两张表中所有的数据对应一遍
这个现象我们也称之’笛卡尔积’无脑的对应没有意义 应该将有关系的数据对应到一起用才合理

基于笛卡尔积可以将部门编号与部门id相同的数据筛选出来

涉及到两张及以上的表时 字段很容易冲突 我们需要字段前面加上表名来指定

select * from emp,dep where emp.dep_id=dep.id;

基于上述的操作就可以将多张表合到一起然后一次性获取更多的数据
————————
  • SQL语句查询关键字
  • 前期数据准备
  • 编写SQL语句的小技巧
  • 查询关键字之where筛选
  • 查询关键字之group by分组
  • 查询关键字之having过滤
  • 查询关键字值distinct去重
  • 查询关键字值order by排序
  • 查询关键字之limit分页
  • 查询关键字之regexp正则表达式
  • 多表查询的思路

SQL语句查询关键字

select
	指定需要查询的字段信息
	select *		查所有字段
	select name		查name字段
	select char_length(name)	支持对字段做处理

from
	指定需要查询的表信息
	from mysql.user
	from t1
	
SQL语句中关键字的执行和编写顺序并不是一致的 可能会错乱
eg:
	select id,name from userinfo;
	我们先写的select在写的from 但是执行的时候是先执行的from再执行select
	
对应关键字的编写顺序和执行顺序没有过多地在意 熟练之后会非常自然的编写 只需要把注意力放在每个关键字的功能上即可

前期数据准备

create table emp(
	id int primary key auto_increment,
    name varchar(32) not null,
    gender enum('male', 'female') not null default 'male'	# 大部分是男的
    age int(3) unsigned not null default 28,
    hire_date date not null,
    post varchar(64),
    post_comment varchar(64),
    salary double(15,2),
    office int,
    depart_id int
);

# 插入记录
insert into emp(name,gender,age,hire_data,post,salary,office,depart_id) values
('jason','male',18,'20170301','浦东第一帅形象代言',7300.33,401,1), #以下是教学部
('tom','male',78,'20150302','teacher',1000000.31,401,1),
('kevin','male',81,'20130305','teacher',8300,401,1),
('tony','male',73,'20140701','teacher',3500,401,1),
('owen','male',28,'20121101','teacher',2100,401,1),
('jack','female',18,'20110211','teacher',9000,401,1),
('jenny','male',18,'19000301','teacher',30000,401,1),
('sank','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);


create table emp(
	id int primary key auto_increment,
	name varchar(16) not null,
    gender enum('male','female') not null default 'male',
    age int(3) unsigned not null default 18,
    hire_date date not null,
    post varchar(64),
    past_comment varchar(100),
    salary double(15,2),
    office int,
    depart_id int

编写SQL语句的小技巧

针对select后面的字段名可以先用*号占位往后写 最后再回来修改

在实际应用中select后面很少直接写*号 因为*号表示所有 当表中字段和数据都特别多的情况下非常浪费数据库资源

'''
SQL语句的编写类似于代码的编写 不是一蹴而就的 也需要反反复复的修修补补
'''

查询关键字之where筛选

  • 查询id大于等于3小于6的数据
select * from emp where id >= 3 and id <= 6;  # 支持逻辑运算符

select * from emp where id bewteen 3 and 6;

  • 查询薪资是20000或者18000或者17000的数据
select * from emp where salary=20000 or salary=18000 or salary=17000;

select * from emp where salary in (20000,18000,17000);  # 支持成员运算
  • 查询id小于3大于6的数据
select * from emp where id<3 or id>6;

select * from emp where id not between 3 and 6;
  • 查询员工姓名中包含字母o的员工姓名与薪资
select * from emp where name like '%o%';

条件不够精确的查询 称之为 模糊查询
模糊查询的关键字是:	like
迷糊查询的常用符号:
%	# 通配符代表零个 一个或多个字符 匹配任意个数的任意字符
eg:
	%o%		o jason owen loo wwoww	匹配所有带o字符与的
	%o		o asdasdo asdo 匹配以o结尾的字符
	
_	# 匹配单个个数的任意字符
eg:
	_o_		aox wob iok
	o_		oi ok ol	
  • 查询员工姓名是由字符组成的员工姓名与其薪资
select * from emp where name like '____';

select * from emp where char_length(name)=4;
  • 查询岗位描述为空的员工名与岗位名 针对null不能用等号 只能用is
select * from emp where post_comment=NULL;	错误不可以
select * from emp where post_comment is NULL;  可以

在MySQL中也有很多的内置方法 我们可以通过查看帮助手册学习 help 方法名

查询关键字之group by分组

分组:按照指定的条件将单个单个的数据组成一个个整体

如:将班级学生按照指定性别分组

将全国人民按照名族分组

将全世界的按照肤色分组

分组的目的是为了更好的统计相关数据

如:每个班级的男女比例

每个人民族的总占比

每个部门的平均薪资

聚合函数

max:最大值 min:最小值 sum:求和 avg:平均值 count:计数

  • 将员工数据按照部门分组
select * from emp group by post;

'''
MySQL5.6默认不会报错
	set global sql_mode='strict_tran_tables,only_full_group_by'
	
MySQL5.7及8.0默认都是会报错的
	原因是分组之后 select后面默认只能填写分组的依据 不能再写其他字段
	select post from emp group by post;
	select age from emp group by age;
	分组之后默认的是最小单位就应该是组 而不应该再是组内的单个数据单个字段
'''
  • 获取每个部门的最高工资
# 要不要 分组我们完全可以从题目中的需求中分析出来尤其是出现的关键字 每个 平均

select post,max(salary) from emp group by post;

针对sql语句执行之后的结果 我们是可以修改字段名称的 关键字as 也可以省略
select post as '部门',max(salary) as '最高薪资' from emp group by post;
  • 一次获取部门薪资相关统计
select post,max(salary) '最高薪资',min(salary) '最低薪资',avg(salary) '平均工资',sum(salary) '月支出' from emp group by post;
  • 统计每个部门的人数
select post,count(id) from emp group by post;
  • 统计每个部门名称以及部门下的员工姓名
# 分组以外的字段无法直接填写 需要借助于方法
select post,name from emp group by post;
select post,group_concat(name) from emp group by post;
select post,group_concat(name,age) from emp group by post;

select post,group_concat(name,'|',age) from emp group by post;
select post,group_concat(name,'_NB') from emp group by post;
select post,group_concat('DSB_',name,'_NB') from emp group by post;

查询关键字之having过滤

having与where本质是一样的 都是用来当对数据做筛选

只不过where用在分组之前(首次筛选)

having用在分组之后(二次筛选)

  • 统计各部门年龄在30岁以上的员工平均工资 并且保留大于10000的数据
对于复杂的点的SQL 跟写代码几乎一样 也是需要提前想好大致思路

# 没一条的结果可以直接看成就是一张表 基于该表如果还想继续操作则直接在生产该表的SQL语句上添加即可

NO1.先筛选出所有年龄大于30岁的员工数据
	select * from emp where age > 30;
NO2.再对筛选出来的数据按照部门分组并统计平均薪资
	select post,avg(salary) from emp where age > 30 group by post;
NO3.针对分组统计之后的结果再做筛选
	select post,avg(salary) from emp where age > 30 group by post having avg(salary) > 10000;

查询关键字值distinct去重

去重有一个必须的条件也是很容易被忽略的条件 数据必须是一模一样才可以去重

select distinct id,age from emp;  关键字针对的得是多个字段组合的结果
select distinct age from emp;
select distinct age,post from emp;

查询关键字值order by排序

  • 可以是单个字段排序
1.可以是单个字段排序
select * from emp order by age;  默认升序
select * from emp order by age asc;  默认升序(asc可以省略)

select * from emp order by age desc;  降序
  • 也可以是多个字段排序
select * from emp order by age,salary desc;  # 先按照年龄升序排 相同的情况下就再按照薪资降序排

统计各部年龄在10岁以上的员工平均工资 并且保留平均工资大于1000的部门 然后对平均工资进行排序

1.先筛选出所有年龄大于10岁的员工
select * from emp where age > 10;

2.再对他们按照部门分组统计平均薪资
select post,avg(salaey) from emp where age > 10 group by post;

3.针对分组的结果二次筛选
select post,avg(salary) from emp where age > 10 group by post having avg(salary)>1000;

4.最后按照指定字段排序
select post,avg(salary) from emp where age > 10 group by post having avg(salary)>1000 order by avg(salary);

'''
当一条SQL语句中很多都需要使用聚合函数计算之后的结果 可以节省操作(主要是节省的底层的运行效率 代码看不出来)
select post,avg(salary) as avg_salary from emp where age > 10 group by post having avg_salary>1000 order by avg_salary;

'''

查询关键字之limit分页

当表中数据特别多的情况下 很少会一次性获取所有的数据 很多网站也是做了分页处理一次性只能看一点点

select * from emp limit 5; 直接限制展示的条数
select * from emp limit 5,5; 从第5条开始往后读取5条

查询工资最高的人的详细信息

# 不要惯性思维 一看到工资就想着用分组聚合

select * from emp order by salary decs limit 1;

查询关键字之regexp正则表达式

SQL语句的模糊匹配如果不习惯 可以自己写正则批量查询
select * from emp where name regexp '^j.*?(n|y)$';

多表查询的思路

数据

表数据准备
create table dep(
  id int primary key auto_increment,
  name varchar(20) 
);

create table emp(
  id int primary key auto_increment,
  name varchar(20),
  sex enum('male','female') not null default 'male',
  age int,
  dep_id int
);

#插入数据
insert into dep values
(200,'技术'),
(201,'人力资源'),
(202,'销售'),
(203,'运营'),
(205,'财务');
insert into emp(name,sex,age,dep_id) values
('jason','male',18,200),
('dragon','female',48,201),
('kevin','male',18,201),
('nick','male',28,202),
('owen','male',18,203),
('jerry','female',18,204);

select * from emp,dep;

会将两张表中所有的数据对应一遍
这个现象我们也称之’笛卡尔积’无脑的对应没有意义 应该将有关系的数据对应到一起用才合理

基于笛卡尔积可以将部门编号与部门id相同的数据筛选出来

涉及到两张及以上的表时 字段很容易冲突 我们需要字段前面加上表名来指定

select * from emp,dep where emp.dep_id=dep.id;

基于上述的操作就可以将多张表合到一起然后一次性获取更多的数据