MySQL(单表查询)
MySQL之查询关键
- 
SQL语句查询关键字
❤️🔥SQL语句查询关键字之select
最基本的查询语句就是由select和from关键字所组成的,select语句屏蔽了物理层的操作,用户不必在意关系数据的真实存储,交互有数据库高效的查询数据。
select:指定需要查询的字段信息
select (空格) :查询所有字段
select name:查询 name 字段
name 字段:查询字段的 字符数
select char_length(name)from :指定需要查询的表信息
from mysql.user from t1在SQL语句中关键字的执行顺序和编写顺序并非是一致的。
eg: select id,name from userinfo; 意思是: 在userinfo这个表中查询id和名字 在书写的的时候,我们是先书写select 然后再写的from,但是在执行的时候是先执行的from 在执行的select。 关于书写的顺序和执行的顺序,没有必要过多的在意,只要足够的熟练,写就成了很自然而然的。 
🐳elect语句中各关键字的先后顺序
(1) from
(2) on
(3) join
(4) where (可以使用表的别名)
(5) group by(可以开始使用select中字段的别名(不是表的别名),后面的语句中都可以使用)
(6) having + 聚合函数
(7) select
(8) distinct
(9) order by
(10) limit
1~3是table部分——形成表
4~6是filter部分——过滤条件
7~10是show部分——展示
❤️🔥查询关键字:==where ==
where子句 :判断数据,进行筛选
where 语法句式:
select ...from ....where  条件(and/or) 条件..
能被使用的判断条件有哪些:
比较运算符: >, <, >=, <= ,!= ,<>, =
逻辑运算符: &&(and), ||(or), !(not)
like:模糊查询
between:在.....中间
like(模糊查询):
概念:模糊查询就当条件不够精确的时候进行查询,就称之为模糊查询
模糊查询的常用符号:
% :可以匹配任意的个数的字符
	eg:%o%   Jason loo  owen 
    	%0    asd0  mio  mico
_ :可以匹配单个个数的任意字符
	eg: _o_    aox  box 
    	o_    ok ol 
小提示:子句的执行顺序是from-> where -> select ,先选择数据来源,再进行条件筛选,根据筛选完的记录选择输出内容
🐳案例:
准备的数据
创建表格的数据
  create table 员工数据(id int primary key auto_increment,
    name varchar(20) 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(50),
    post_comment varchar(100),
    salary double(15,2),
    office int, #一个部门一个屋子
    depart_id int);
  #插入记录
  #部门:教学部、销售部、运营部
  insert into 员工数据 (name,gender,age,hire_date,post,salary,office,depart_id) values('水清璃','male',1000,'20130109','水的诞生者',1000000,101,1),('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),#以下是销售部门
  ('天明','male',38,'20101101','sale',2000.35,402,2),
  ('少羽','male',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);
🐳编写SQL语句的小技巧
针对select后面的字段名我们可以先使用 * 占位然后再往后写,最后在回来修改
	但是在实际应用select 的后面直接写 * ,因为 * 的意思就是所有,当表中字段和数据都特别多的情况下是非常浪费数据库资源的。
PS:SQL语句的编写和代码是一样的,都是来来回回的修改,反反复复的编写,从而完成的,而不是一蹴而就的。出现了问题一定不要慌,慢慢来,先看报错信息,在根据报错的信息进行处理。
🐳where实践:
1.查询id大于等于3小于等于6的数据
	select * from 员工数据 where id >=3 and<=6;
	select *from 员工数据 where id between 3 and 6;
2.查询薪资是20000或者18000或者17000的数据
	select * from 员工数据 where salary=20000 or salary=18000 or salary =7000;
3.查询id小于3大于6的数据
  	select *from 员工数据 where id<3 or id>6;
4.查询员工姓名中包含字母o的员工姓名与薪资
	select *from 员工数据 where name like '%o%';
5.查询员工姓名是由四个字符组成的员工姓名与其薪资
	(1)select * from 员工数据 where name like '____' and salary;
(2)select *from 员工数据 where char_length(name) =4;
6.查询岗位描述为空的员工名与岗位名  针对null不能用等号,只能用is
	select *from 员工数据 where post_comment is null;
❤️🔥查询关键字:group by(分组)
🐳概念:主要是用来进行分组查询的,通过一定的规则将一个个数据集进行划分,然后针对每个小组的区分分别进行数据的汇总处理,分组的目的就是为了更好的统计相关的数据。
语法结构:
select (组名) from 表名 group by 字段名;
🐳在进行分组的时候,SQL提供了如下聚合函数,如下:
Count(): 统计分组后的记录数: 每一组有多少记录
Max(): 统计每组中非空的最大值
Min(): 统计非空的最小值
Avg(): 统计平均值
Sum(): 统计和
avg()函数:
分组以外的字段是无法直接写的,需要借助于方法,可以对分组的结果中的某个字段进行字符串连接(保留该组所有的某个字段):
    group_concat(字段)
小提示:语句的执行顺序如下:
from -> where -> group by -> select-> order by -> limit
from选择数据来源,where选择条件,符合条件的记录留下来,然后经过group by分组,分完组根据select子句里面聚合函数做计算,然后order by对结果集排序,最后交给limit挑选返回哪些分页的数据显示。
还有一点就是where 条件是不允许出现聚合函数的。
🐳实践:
1.将员工数据按照部门分组
	select *from 员工数据 group by post;(无序?)
    SQL_mode = 'strict_trans_table,only_full_group_by'
    
2.获取每个部门的最高工资
"""对于分组,我们在使用的过程中完全可以从需求中分析出来, 尤其是出现了关键字  每个,平均 """
select post,max(salary) from 员工数据 group by post;
3.一次获取部门薪资相关统计
	select post,max(salary)'最高薪资',min(salary)as '最低薪资',avg(salary)'平均薪资',sum(salary)'本月支出' from 员工数据 group by post;
4.统计每个部门的人数
	select post,count(id) from 员工数据 group by post;
5.统计每个部门的部门名称以及部门下的员工姓名
"""分组以外的字段没有办法直接填写的,需要借助到一个小方法 group_concat (拼接)"""
 	select post,group_concat(name) from 员工数据 group by post;
    select post,group_concat(name,'|',age) from 员工数据 group by post; 
    #(拼接的时候可以添加一些特殊的符号)
在针对SQL语句执行之后的结果,我们是可以修改字段的名称的,使用关键字 as  (在输写的时候也可以进行省略)
如下:
select post as '部门',max(salary)'最高薪资' from 员工数据 group by post;


回溯统计: with rollup: 任何一个分组后都会有一个小组, 最后都需要向上级分组进行汇报统计: 根据当前分组的字段. 这就是回溯统计: 回溯统计的时候会将分组字段置空.
多字段回溯: 考虑第一层分组会有此回溯: 第二次分组要看第一次分组的组数, 组数是多少,回溯就是多少,然后加上第一层回溯即可.
select post,avg(salary) from 员工数据 group by post with rollup;

❤️🔥查询关键字:having (过滤)
🐳概念:having的本质与where是一样的,都是用来对数据进行筛选,只不过where是在分组前 进行的筛选,而having是对分组之后对数据进行筛选(二次筛选)。
上面说了where判断条件中是不能出现聚合函数的,而having的出现就是为where解决where条件不能使用聚合函数的问题。
having (条件)不能独立存在,必须依赖于group by()而存在,group by 执行完成就立即执行having子句
语法结构:
select 分组 *from 表名 where (where条件) group by 分组名 having (having条件);
从功能上来说,上面两种写法没有什么区别,但是where优先级在group by之前,是先把数据按条件筛选完了再分组好呢,还是分完组再去筛选好呢?肯定是前者。所以where能完成的就用where完成,不要放到having中。大量的数据从磁盘读取到内容代价比较大,先筛选完了,再把符合条件的记录读取到内存中显然更好。
Having能做where能做的几乎所有事情, 但是where却不能做having能做的很多事情.
where 与having的区别:
1.分组统计的结果或者说统计函数都只有having能够使用.
2.having能够使用字段别名,where不能,where是从磁盘取数据,而名字只可能是字段名,别名是在字段进入到内存后才会产生.
🐳代码实践:
1.统计各部门年龄在30岁以上的员工平均工资 并且保留大于10000的数据
推理步骤:
(1).先筛选出所有年龄大于30岁的员工数据
	select * from 员工数据 where age > 30;
(2).在对筛选出来的数据按照部门的分组进行统计平均薪资
	select post,avg(salary) from 员工数据 where age > 30 group by post;
 (3).针对已经分组统计之后的结果做二次筛选
	select post,avg(salary) from 员工数据 where age>30 group by post having avg(salary) >1000;

要注意having 子句判断只能和具体数值判断大小,不能和字段以及聚合函数判断,比较要有数值。比如查询工资大于平均工资的人的数量就不能写having salary > avg(salary),子句判断不是和数值在比较,会直接报错。
❤️🔥查询关键字:distinct(去重)
🐳概念:针对两个一模一样的两个数据进行去重处理(注意这里的这个条件是不能被忽略的)
语法结构:
select distinct 去重关键字 from 表名;
关键字针对的是多个字段组合的结果
实践:
1.查看员工中的所有年龄段
select distinct age from 员工数据;
2.查看每个部门的都有哪些年龄段的人
select distinct age,post from 员工数据;

❤️🔥查询关键字:order by (排序)
🐳概念:就是根据某个字段进行排序(升序或降序)
语法结构:
order by 字段名 [asc/desc]  
asc:  升序(默认的)
desc:降序
🐳多字段的排序:
使用order by 规定的首要条件和次要条件排序,数据库会优先按照首要条件进行排序;遇到首要排序内容相同的记录,那么就会启动次要的条件再次进行排序就可以了。
实践:
1.单字段排序
select * from 员工数据 order by age asc; #(默认升序 asc 可以省略)
select *from 员工数据 order by age desc;#(降序)
2.多字段排序
2.1.先按照年龄进行排序,然后再相同的结果下按照薪资降序
select *from 员工数据 order by age,salary desc;
2.2.统计个部门年龄在18岁以上的员工平均工资,并且保留平均工资大于1000的部门,然后对工资进行排序
	执行步骤:
    1.先筛选所有年龄大于18岁的员工
    select *from 员工数据 where age>=18;
    2.对部门进行分组再统计员工的平均工资
    select post,avg(salary) from 员工数据 where age>=18 group by post;
    3.统计平均工资大于1000的部门
    select post,avg(salary) from 员工数据 where age>=18 group by post having avg(salary) >1000 ;
    4.对所有的工资进行排序
    select post,avg(salary) from 员工数据 where age>=18 group by post having avg(salary) >1000  order by avg(salary);

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

❤️🔥查询关键字:limit (分页)
🐳概念:这是一种限制结果的语句,用来对数据进行分页。当数据在特别多的情况下,我们很少会一次性获取所有的数据。
例如:我们浏览网站,一般只会加载少量的部分信息,并不会一次性将所有的数据加载出来,那样只会浪费CPU时间,内存,网络,网络带宽。而结果集的记录可能很多,所以可以使用limit关键字来限定结果集的数量。
🐳limit的两种使用方式:
- 
用来限制长度(数据量)
语句结构:limit(数据量) - 
用来限制起始位置,限制数
语句结构:limit 起始位置,长度 
方式2主要用来实现数据的分页: 为用户节省时间,提交服务器的响应效率, 减少资源的浪费.
对于用户来讲: 可以点击的分页按钮: 1,2,3,4....
对于服务器来讲: 根据用户选择的页码来获取不同的数据: limit offset,length;
Length: 每页显示的数据量: 基本不变
Offset: offset = (页码 - 1) * 每页显示量
小提示:limit子句的执行顺序 from -> select -> limit,先选择数据来源,再选择输出内容,最后选择显示的限定条件
实践:
1.展示五个员工的数据
select *from 员工数据 limit 5;
2.从第二条之后到读取9条数据
select *from 员工数据 limit 2,9;
3.查询工资最高的人的信息
select *from 员工数据 order by salary desc limit 1;
#这里千万不能使用惯性思维,一看到工资最高就想想着分组聚合

❤️🔥查询关键字:regexp (正则表达式)
🐳在使用SQL语句的模糊匹配如果用的不习惯,自己也可以写正则表达式来进行批量查询
# 开头条件是 j 结尾:n 或y
改:select *from 员工数据 where name regexp '^j.*(n|y)$'; 

❤️🔥关于多表查询:
🐳概念:将多张表(可以大于2张)进行记录的链接(按照某一个指定的条件进行数据的拼接)。
我们会将两张表中的所有的数据对应一遍,这个现象称之为"笛卡尔积",因为无脑的对应是没有意义的,应该将关系的数据对应到一起才合理。基于笛卡尔积可以将两个表中的部门编号和部门id相同的数据筛选出来,涉及到两张及以上的表时,
最终结果会是:记录数有可能会发生改变,字段数一定会增加(至少会是两张合并),字段就很容易冲突,所以我们需要在字段前面加上表名来进行指定。
🐳连接查询的意义: 在用户查看数据的时候,需要显示的数据来自多张表.
create table 部门表(
id int primary key auto_increment,
name varchar(32));
create table 员工表(
id int primary key auto_increment,
name varchar(32),
sex enum('male','female') not null default 'male',
    age int,
    部门号 int);
#添加数据
insert into 部门表 values
(1,'技术部'),
(2,'销售部'),
(3,'财务部'),
(4,'运营部'),
(5,'秘书部');
insert into 员工表 (name,sex,age,部门号)values
('莫言','male',28,1),
('林玖','male',24,2),
('夏夏','female',23,3),
('姜虹','male',28,4),
('默默','female',28,5);
1.将两张表的数据进行合并
select *from 员工表,部门表;
2.获取合在一起的两张表一次性获取更多的数据
select *from 员工表,部门表 where 员工表.部门号=部门表.id;


                
            
        
浙公网安备 33010602011771号