mysql 单表查询 & 多表查询 & 子查询

单表查询

  • sql查询语句的完整语法

    select .. from .. where .. group by .. having .. order by .. limit ..
    
  • where条件的使用

    • 功能:对表中的数据进行筛选和过滤

    • 语法:

      1.判断的符号:
       =  >   >=  <  <=   !=    <>不等于
      2.拼接条件的关键字
       and or not
      3.查询的区间范围值 between
       between 小值  and  大值  [小值,大值]  查询两者之间这个范围内所有值
      4.查询具体某个值的范围 in
       in(1,2,3)指定的范围
      5.模糊查询like ‘%‘ 通配符
       like ‘%a‘  匹配以a结尾的任意长度的字符串
       like ‘a%‘  匹配以a开头的任意长度的字符串
       like ‘%a%‘ 匹配含有a字母的任意长度的字符串
       like ‘_a‘  个数一共是2个字符,必须以a结尾,前面的字符随意
       like ‘a__‘ 个数一共是3个字符,必须以a开头,后面的字符随意
      
    • 查询练习

      create database db0618;
      use db0618;
      
      create table employee(
      id int not null unique auto_increment,
      emp_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
      );
      
      mysql> desc employee;
      +--------------+-----------------------+------+-----+---------+----------------+
      | Field        | Type                  | Null | Key | Default | Extra          |
      +--------------+-----------------------+------+-----+---------+----------------+
      | id           | int(11)               | NO   | PRI | NULL    | auto_increment |
      | emp_name     | varchar(20)           | NO   |     | NULL    |                |
      | sex          | enum(‘male‘,‘female‘) | NO   |     | male    |                |
      | age          | int(3) unsigned       | NO   |     | 28      |                |
      | hire_date    | date                  | NO   |     | NULL    |                |
      | post         | varchar(50)           | YES  |     | NULL    |                |
      | post_comment | varchar(100)          | YES  |     | NULL    |                |
      | salary       | double(15,2)          | YES  |     | NULL    |                |
      | office       | int(11)               | YES  |     | NULL    |                |
      | depart_id    | int(11)               | YES  |     | NULL    |                |
      +--------------+-----------------------+------+-----+---------+----------------+
      10 rows in set (0.00 sec)
      
      ###单条件查询
      #查询部门是sale的所有员工姓名;
      select emp_name from employee where post = ‘sale‘;
      
      ###多条件的查询
      #部门是teacher,收入大于10000的所有数据
      select * from employee where post=‘teacher‘ and salary>10000;
      
      ###关键字between .. and..
      #收入在1万到2万之间的所有员工姓名和收入
      select emp_name,salary from employee where salary between 10000 and 20000;
      #收入不在1万到2万之间的所有员工姓名和收入
      select emp_name,salary from employee where salary not between 10000 and 20000;
      
      ### null 关键字 在查询的时候,要用is进行判定,不要用=
      #查询post_comment是空的所有数据
      select * from employee where post_comment is null;
      #查询post_comment不是空的所有数据
      select * from employee where post_comment is not null;
      
      #查询空值
      update employee set post_comment = ‘‘ where id = 1;
      select * from employee where post_comment = ‘‘;
      
      # 关键字 in 在..之中 查询
      #查询收入是3000,4000,5000,8000所有员工的姓名和收入
      select emp_name,salary from employee where salary=3000 or salary=4000 or salary=5000 or salary=8000
      #用in优化,在小括号里面具体指定某个值
      select emp_name,salary from employee where salary in(3000,4000,5000,8000);
      #不在 not in ..
      select emp_name,salary from employee where salary not in(3000,4000,5000,8000);
      
      #模糊查询like ‘%‘ ‘_‘通配符
      # ‘%‘通配符 以on结尾的员工姓名
      select emp_name,age,post from employee where emp_name like ‘%on‘
      # ‘_‘ 通配符可以限定具体的长度
      select emp_name,age,post from employee where emp_name like ‘a_e_‘
      
      #concat 拼接  (as 起别名)
      select concat(‘姓名:‘,emp_name,‘工资:‘,salary) from employee;
      select concat(‘姓名:‘,emp_name,‘工资:‘,salary) as aa from employee;
      #concat_ws(拼接的符号,参数1,参数2,参数3...)
      select concat_ws(‘:‘,emp_name,salary) from employee
      #计算年薪 可以在mysql中使用四则运算(+ - * /)
      select concat_ws(‘:‘,emp_name,salary*12) as cc from employee;
      
    • group by子句 分组分类

      • group by 字段 对数据进行分类,by后面接什么字段,select就搜索什么字段

        #按照性别进行分类
        select sex from employee group by sex;
        #按照部门进行分类
        select post from employee group by post;
        
      • group_concat 按照分类的形式进行字段的拼接

        select group_concat(emp_name),post from employee group by post;
        
      • 聚合函数

        #count 统计总数 *所有
        select count(*) from employee;
        #max 统计最大值
        select max(salary) from employee;
        #min 统计最小值
        select min(salary) from employee;
        #avg 统计平均值
        select avg(salary) from employee;
        #sum 统计总和
        select sum(salary) from employee;
        
      • 一般情况 分组 + 聚合函数 配合使用

        #查询部门名以及各部门的平均薪资
        select post,avg(salary) from employee group by post;
        #查询部门名以及各部门的最高薪资
        select post,max(salary) from employee group by post;
        #查询部门名以及各部门的最低薪资
        select post,min(salary) from employee group by post;
        #查询公司内男员工和女员工的个数
        select sex,count(*) from employee group by sex;
        #查询部门名以及部门包含的所有员工名字
        select group_concat(emp_name) from employee group by post
        #可以group by两个字段,即可搜索两个字段
        select emp_name,post from employee group by post,emp_name;
        
    • having 数据在分类分组之后,进行二次数据过滤,一般是配合group by 使用,分组之后再过滤

      #找出各部门平均薪资,并且大于10000以上的所有部门
      select post,avg(salary) from employee group by post having avg(salary)>10000;
      #查询各岗位内包含的员工个数小于2的岗位名、查询岗位内包含员工名字、个数
      select post,group_concat(emp_name),count(*) group by post having count(*) <2
      #查询各岗位平均薪资小于10000的岗位名、平均工资
      select post,avg(salary) from employee group by post having avg(salary) < 10000
      #查询各岗位平均薪资大于10000且小于20000的岗位名、平均工资
      select post,avg(salary) from employee group by post having avg(salary) between 10000 and 20000;  #between 10000 and 20000 这两个值可以取到
      select post,avg(salary) from employee group by post having avg(salary)>10000 and avg(salary)<20000;  
      
    • order by排序 ,按照什么字段进行排序

      • asc 升序:从小到大(默认)
      • desc 降序:从大到小
      select * from employee order by age #(asc 默认升序)
      select * from employee order by age desc #(desc 降序)
      
      #查询所有员工信息,先按照age升序排序,如果age相同则按照hire_date降序排序
      select emp_name,age,hire_date,post from employee order by age,hire_date desc;
      #查询各岗位平均薪资大于10000的岗位名、平均工资,结果按平均薪资升序排列
      select post,avg(salary) from employee group by post having avg(salary)>10000 order by avg(salary)
      #查询各岗位平均薪资大于10000的岗位名、平均工资,结果按平均薪资降序排列
      select post,avg(salary) from employee group by post having avg(salary)>10000 order by avg(salary) desc;
      
    • limit 限制查询条数(数据分页)

      • limit m,n m代表从第几条数据查询,n代表查询几条,m=0代表的是第一条
      select * from employee limit 0,5 从第一条数据开始搜,搜5条
      select * from employee limit 5,5 从第六条数据开始搜,搜5条
      #只查询一条数据
      select * from employee limit 1
      #找数据库当中最后一条数据
      select * from employee order by id limit 1
      #找数据库当中最后三条数据
      select * from employee order by id limit 3
      
    • 使用正则表达式查询数据(不推荐使用,效率不高)

      select * from employee where emp_name regexp ‘.*on$‘; #.*?  问号?不识别
      select * from employee where emp_name regexp ‘^程‘;
      select * from employee where emp_name regexp ‘^程.*金‘;
      

多表查询

  • 练习

    #建表
    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,
    de_id int
    );
    
  • 内连接:(内联查询 inner join)-> 查询两表或者多表满足条件的所有数据被查询出来(两表之间共有的部分)

    #两表查询
    #select 字段 from 表1 inner join 表2 on 必要的关联条件
    #多表查询
    #select 字段 from 表1 inner join 表2 on 必要的关联条件1 inner join 表3 on 必要的关联条件2...
    #基本语法 inner join on .. on后面接必要的关联条件
    select * from employee inner join department on employee.dep_id = department.id;
    #用as 起别名(推荐)
    select * from employee as e inner join department as d on e.dep_id = d.id;
    # as 可以省略掉
    select * from employee e inner join department d on e.dep_id = d.id;
    
    #where默认实现的就是内联查询的效果
    select * from employee,departmet where employee.dep_id = department.id;
    select * from employee as e,department as d where d.dep_id = d.id;
    
  • 外连接

    • 左连接(左联查询 left join)以左表为主,右表为辅,完整查询左表所有数据,右表没有的数据补null

      select * from employee left join department on employee.dep_id = department.id;
      
    • 右连接(右联查询 right join)以右表为主,左表为辅,完整查询右表所有数据,左表没有的数据补null

      select * from employee right join department on employee.dep_id = department.id;
      
    • 全连接(全连接 union)所有的数据都合并起来

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

子查询

  • 子查询:嵌套查询
    • sql语句当中又嵌套了另外一条sql语句,用括号()抱起来,表达一个整体
    • 一般应用在from子句后面表达一张表 where子句后面表达一个条件
    • 查询速度从快到慢:单表查询 -> 联表查询 ->子查询
#找出平均年龄大于25岁以上的部门
1.普通where写法
select
	d.id,d.name
from
	employee as e,department as d
where
	e.dep_id = d.id
group by
	d.id,d.name
having
	avg(e.age)>25;
2. inner join
select
	d.id,d.name
from
	employee as e inner join department as d on e.dep_id=d.id
group by
	d.id,d.name
having
	avg(e.age)>25;
3.子查询
 (1)先找出平均年龄大于25岁的部门id
select dep_id from employee group by dep_id having avg(age)>25;
 (2)通过部门id,找部门名字
select name from department where id in(201,202);
 (3)综合拼接
select name from department where id in(select dep_id from employee group by dep_id having avg(age)>25);
#查看技术部门员工姓名
1.普通where查询
select
	e.name
from
	department as d,employee as e
where
	d.id = e.dep_id
    and
    d.name = ‘技术‘;
2.inner join写法
select
	e.name
from
	department as inner join demployee as e on d.id = e.dep_id
where
    d.name = ‘技术‘;
3.子查询写法
 (1)找技术部门对应id
    select id from department where name = ‘技术‘;
 (2)通过id找员工姓名
	select name from employee where dep_id = 200;
 (3)综合拼接
	select name from employee where dep_id = (select id from department where name = ‘技术‘);
#查看那个部门没员工
 (1)联表写法(把null的数据露出来,员工的部门dep_id 为null,代表这个部门没人)
select 
	d.id,d.name  
from
	department as d,employee as e on d.id = e.dep_id
where 
	e.dep_id is null
  (2)子查询
	1.先查询,员工在那些部门(所有员工的分类分别是200 201 202 204)
    select dep_id from employee group by dep_id;
    2.把不在部门的数据找出来
    select from department where id not in (200,201,202,204);
    3.联合拼接
    select from department where id not in (select dep_id from employee group by dep_id)
#查询大于平均年龄的员工名与年龄
 1.假设平均年龄是20岁
    select name,age from employee where age >20
 2.找平均年龄
	select avg(age) from employee;
 3.综合拼装
	select name,age from employee where age >(select avg(age) from employee);
  
#把大于其本部门平均年龄的员工名和姓名查出来
 1.先计算各部门平均年龄是多少
    select dep_id,avg(age) from employee group by dep_id;
 2.把查询的各部门的平均年龄和过去的employee联表,变成一张更大的表,方便做一次单表查询
	select
    	*
    from
    	employee as t1 inner join (1号查询到的数据) as t2 on t1.dep_id = t2.dep_id
 3.综合拼接
	select
    	*
    from
    	employee as t1 inner join (select dep_id,avg(age) as avg_age from employee group by dep_id) as t2 on t1.dep_id = t2.dep_id
 4.做最后的数据筛选 age > 平均年龄
   select
    	*
    from
    	employee as t1 inner join (select dep_id,avg(age) as avg_age from employee group by dep_id) as t2 on t1.dep_id = t2.dep_id
     where
    	t1.age>t2.avg_age

#查询每个部门最新入职的那位员工 #利用上一套数据表进行查询;
1.找每个部门最大的入职时间
select post,max(hire_date) as max_date from employee group by post  
2.把子查询搜出来的数据和employee联合成一张更大的表,做一次单表查询
select
	t1.emp_name,t1.hire_date
from
	employee as t1 inner join(1号查出来的数据) as t2 on t1.post = t2.post
where
	t1.hire_date = t2.max_date
 3.综合拼接
select
	t1.emp_name,t1.hire_date
from
	employee as t1 inner join(select post,max(hire_date) as max_date from employee group by post) as t2 on t1.post = t2.post
where
	t1.hire_date = t2.max_date
#带EXISTS关键字的子查询
#exists 关键字,表达存在;
#如果内层sql能够查到数据,返回True,外层sql执行查询语句
#如果内层sql能够查到数据,返回False,外层sql不执行查询语句
select * from employee where exists (select * from employee where id = 1)
  • 子查询总结:
    • 子查询可以单独作为一个临时数据,临时的表,临时的字段
    • 一般用在from where select 子句后面
    • 用法在于可以通过查询出来的临时数据和另外的表联合,变成一张更大的表,在做单表查询查到想要的数据

mysql 单表查询 & 多表查询 & 子查询

上一篇:MySQL alter修改语句


下一篇:分享Sql性能优化的一些建议