MySQL之表查询

Posted mofujin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL之表查询相关的知识,希望对你有一定的参考价值。

语法执行顺序

  

from >>>从那张表

where >>> 全局的筛选条件

group by>>> 必须是用在where  之后


having >>> 和group by 一起连用 必须放在group by 之后

oder by 对于晒选出来的结果 进行 排序 默认asc 升序 desc 是降序

distinct  >>> 去重 必须是在select展示结果的时候进行 去重

limit  也是用在前面的提条件之后

是对于数据的展示条数的限制

一.查询顺序

  1.1.语法执行顺序

1.1.语法执行顺序
# # 1.查询id大于等于3小于等于6的数据
    select * from emp where id >=3 and id <= 6;
    # 先后顺序
    from    >>>从那张表 数据的来源
    where   >>>的限制条件 
    selecct >>>最终展示我们想要的数据

  1.2.where约束条件

# 2.查询薪资是20000或者18000或者17000的数据
    
    # 这里有两种方法 
    select  * from emp where salary=20000 or salary=18000 or salary=17000;
    
    # 可以用in 方法
    
    select * from emp where salary in (20000,18000,17000);

mysql> select * from emp where salary in (20000,18000,17000);

+----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
    | id | name      | sex    | age | hire_date  | post      | post_comment | salary   | office | depart_id |
    +----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
    | 15 | 程咬金    | male   |  18 | 1997-03-12 | operation | NULL         | 20000.00 |    403 |         3 |
    | 17 | 程咬铜    | male   |  18 | 2015-04-11 | operation | NULL         | 18000.00 |    403 |         3 |
    | 18 | 程咬铁    | female |  18 | 2014-05-12 | operation | NULL         | 17000.00 |    403 |         3 |
    +----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+


  # 3.查询员工姓名中包含o字母的员工姓名和薪资

# 模糊匹配 关键字like 
    select name,salary from  emp  where name like %o%;
    
    # 细心点 匹配所有带o名字的字母

  # 4.查询员工姓名是由四个字符组成的员工姓名与其薪资

select name,salary from emp where name like ____;
    
    # % 是匹配所有的
    # _ 一个下划线匹配一个 注意事项:_ 引号内
    
    方法二#char_length
    select name,salary from emp where char_length(name)=4;


  # 5.查询id小于3或者大于6的数据 集体数据

select * from emp where not id >=3 or id <=6;
select * from emp where not id <3 or id >6;

1.2.where约束条件


  #6.查询薪资不在20000,18000,17000范围的数据

select * from emp where salary not in (20000,18000,17000);


select name,salary from emp where salary not in (20000,18000,17000);

  # 7.查询岗位描述为空的员工名与岗位名 

     select name,post from emp where post_comment is NULL;
     
    # 查询SQL语句中为空的信息字段不能post_comment=Null 只能用is=Null;

3.group by   

  # 1.按部门分组  这里没有where 限制条件 

select post from emp group by post;

mysql> select post from emp group by post; # by 后面根要按照什么分组
+-----------------------------+
| post |
+-----------------------------+
| operation |
| sale |
| teacher |
| 张江第一帅形象代言 |
+-----------------------------+

  # 2.获取每个部门 的 最高工资   #  先分组 再用聚合函数 sum() avg() max() min()

from  >>>  那张表 表名 
    where >>> 第一层大的限制条件
    group by >>> 进行分组后是最小的单位 不能直接获取下面的具体值 可以group_concat()
    
    select  >>> 展示最高工资 这是进行最后展示的操作
    
    # 这里没有where 限制条件(全局)
    select post, max(salary) from emp group by post;
    mysql> select post, max(salary) from emp group by post;
    +-----------------------------+-------------+
    | post                        | max(salary) |
    +-----------------------------+-------------+
    | operation                   |    20000.00 |
    | sale                        |     4000.33 |
    | teacher                     |  1000000.31 |
    | 张江第一帅形象代言          |     7300.33 |
    +-----------------------------+-------------+

  # 3.查询分组之后的部门名称和每个部门下所有的员工姓名

# 一般按照分组之后 组就是最小的单位 但是可以 分组的group_concat()方法获取
select post,group_concat(name),count(id) from emp group by post;
# 展示是按照你的写的顺序添加的字段 只要有结果就会一一显示

  # 4.补充concat(不分组时用)拼接字符串达到更好的显示效果 as语法使用

# concat 没有分组的时候就是类似与字符串的拼接的功能 已达到整齐的显示结果
    
    如 : 显示名字和分组
    select concat("姓名:",name) as 名字,concat("工资:", salary)as 工资 from emp group by post having avg(salary)>2000;
    
        +---------------+-------------------+
    | 名字          | 工资              |
    +---------------+-------------------+
    | 姓名:张野     | 工资:10000.13     |
    | 姓名:歪歪     | 工资:3000.13      |
    | 姓名:egon     | 工资:1000000.31   |
    | 姓名:jason    | 工资:7300.33      |
    +---------------+-------------------+
    4 rows in set (0.00 sec)
    
    # 注意:这里的concat作用是拼接字符串 还可以将表头 一关键字as 起别名 
    # 注意2:还就就是要分几个表头就 用几个contcat 进行分列 展示 concat 进行字符串的拼接

  5.# 查询四则运算及聚合函数 sum avg max min 

# 查询每个人的年薪
    # 重表中 获取name 和 salary* 12 就是年薪了
    select name,salary*12 from emp;
    mysql> select name,salary*12 from emp;
    +-----------+-------------+
    | name      | salary*12   |
    +-----------+-------------+
    | jason     |    87603.96 |
    | egon      | 12000003.72 |
    | kevin     |    99600.00 |
    | tank      |    42000.00 |
    +-----------+-------------+
     还有很多就不一一列举了

练习:

  

 
    # 刚开始查询表,一定要按照最基本的步骤,先确定是哪张表,再确定查这张表也没有限制条件,再确定是否需要分类,最后再确定需要什么字段对应的信息

    1. 查询岗位名以及岗位包含的所有员工名字
    # 岗位为post group_concat(name):岗位里包含所有人的名字
     select post,group_concat(name) from emp group by  post;
     
    2. 查询岗位名以及各岗位内包含的员工个数
    select post, count(id) from emp group by post;
    
    3. 查询公司内男员工和女员工的个数
    select sex,count(id) from emp group by sex;
        +--------+-----------+
    | sex    | count(id) |
    +--------+-----------+
    | male   |        10 |
    | female |         8 |
    +--------+-----------+
    2 rows in set (0.00 sec)
    
    4. 查询岗位名以及各岗位的平均薪资
    
    select post,avg(salary) from emp group by post;
    
    +-----------------------------+---------------+
    | post                        | avg(salary)   |
    +-----------------------------+---------------+
    | operation                   |  16800.026000 |
    | sale                        |   2600.294000 |
    | teacher                     | 151842.901429 |
    | 张江第一帅形象代言          |   7300.330000 |
    +-----------------------------+---------------+
    4 rows in set (0.00 sec)
    
    5. 查询岗位名以及各岗位的最高薪资
    
    select name,post,max(salary) from emp group by post;
    # m名字可以自己家帮我们展示每个部分的最高工资的人
    
    6. 查询岗位名以及各岗位的最低薪资
    select post,min(salary)from emp group by post;
    # 注意分组之后只能拿到分组的这个组作为最小的单位 其他信息没有办法拿到
    # 可以通过group_concat()获取name的信息
    
    
    7. 查询男员工与男员工的平均薪资,女员工与女员工的平均薪资
    select sex, avg(salary) from emp group by sex;
    
    
    mysql> select sex, avg(salary) from emp group by sex;

    
    mysql> select sex, avg(salary) from emp group by sex;
    
    +--------+---------------+
    | sex    | avg(salary)   |
    +--------+---------------+
    | male   | 110920.077000 |
    | female |   7250.183750 |
    +--------+---------------+
    2 rows in set (0.00 sec)

4.having 

from

where


group by 必须在where 之后 才能使用

having 必须是和group by 一起使用 而且必须在分组之后

select

例如: 

  1、统计各部门年龄在30岁以上的员工平均工资,并且保留平均工资大于10000的部门

    select post,avg(salary) from emp  where age >=30 group by  post having avg(salary)>10000;


5.distinct

# 去重对于 是在select 之后 执行 distinct

select distinct age from emp ; 将重复的年纪去除

6.order by: 排序  展示 

 列如:

  

#先按照age降序排,在年轻相同的情况下再按照薪资升序
        select name,age,salary from  emp order by age ,salary desc;
        select * from  emp order by age ,salary desc;
        # asc 是默认升序
        # desc  降序排列
        
    # 统计各部门年龄在10岁以上的员工平均工资,并且保留平均工资大于1000的部门,
        然后对平均工资进行排序
        select post ,avg(salary) from emp where age >30 group by post having avg(salary)>1000
        order by avg(salary) desc;
        +---------+---------------+
        | post    | avg(salary)   |
        +---------+---------------+
        | teacher | 255450.077500 |
        | sale    |   2500.240000 |
        +---------+---------------+
        

7.limit

  # 限制查询的条数

select id,name,post,salary from emp limit 0,5; >0 所以重第一条开始
        
        # 展示=内容我们可以自己设定字段
        # 0信息是信息的起始位 表示从1 开始 往后读取5条信息
        
        # select * from emp limit 5,10; 不包含5 从第六条开始

8.正则

select * from emp where name regexp ‘^j.*(n|y)$‘;

# 以 j 开始 . 是除换行服 外的任意字符 * 是别 (n|y)$ n或结尾


二.多表查询
表创建

  select * from emp,dep; 


# 建表
create table dep(id int ,name varchar(20));



# 建emp表
create table emp(id int primary key auto_increment,
name varchar(28),
sex enum("male","female") not null default "male",
age int ,
dep_id int );


#  插入值dep

insert into dep values
(200,‘技术‘),
(201,‘人力资源‘),
(202,‘销售‘),
(203,‘运营‘);

# emp的值

insert into emp(name,sex,age,dep_id) values
(‘jason‘,‘male‘,18,200),
(‘egon‘,‘female‘,48,201),
(‘kevin‘,‘male‘,38,201),
(‘nick‘,‘female‘,28,202),
(‘owen‘,‘male‘,18,200),
(‘jerry‘,‘female‘,18,204)
;

 


# 分表为了方便管理
# 合表为方便查询

1.表查询
# 同时查两张表
select * from emp,dep;
# 左表的一条记录与右表所有几率都对应一遍 >>> 笛卡尔积
# 缺点:
所有的表都对应了一遍,很显然是不合理的,现在我们需要做的就是找出合理多核数据

  #1. 查询员工及所在的部门信息
  select * from emp,dep where emp.dep_id = dep_id;

# 查询部门为技术部的员工及部门信息
        mysql> select * from emp;
            +----+-------+--------+------+--------+
            | id | name  | sex    | age  | dep_id |
            +----+-------+--------+------+--------+
            |  1 | jason | male   |   18 |    200 |
            |  2 | egon  | female |   48 |    201 |
            |  3 | kevin | male   |   38 |    201 |
            |  4 | nick  | female |   28 |    202 |
            |  5 | owen  | male   |   18 |    200 |
            |  6 | jerry | female |   18 |    204 |
            +----+-------+--------+------+--------+
        mysql> select * from dep;
            +------+--------------+
            | id   | name         |
            +------+--------------+
            |  200 | 技术         |
            |  201 | 人力资源     |
            |  202 | 销售         |
            |  203 | 运营         |
            +------+--------------+


  2.# 需求 查询jason的部门

# 思路从emp员工中可以查到 jason dep_id

# 再通过jason 的dep_id 的 对应哪个部门

 


select * from emp where emp.dep_id=dep.id and dep.name = ‘技术‘;

# Unknown column ‘dep.id‘ in ‘where clause‘

  # 系统内部会"dep_id" 不存在改字段  >>> 所以我们需要用到内连接

  (1)# 1.内链接 inner join  只取两张表有对应关系的记录

select * from emp inner join dep on emp.dep_id =dep.id where dep.name=‘技术‘;  查询所有能id he技术能关联的内表

select * from emp inner join dep on emp.dep_id =dep.id where dep.name=‘技术‘and emp.name=‘jason‘;


select * from emp inner join dep on emp.dep_id =dep.id where dep.name=‘技术‘and emp.name=‘jason‘;
+----+-------+------+------+--------+------+--------+
| id | name | sex | age | dep_id | id | name |
+----+-------+------+------+--------+------+--------+
| 1 | jason | male | 18 | 200 | 200 | 技术 |
+----+-------+------+------+--------+------+--------+
1 row in set (0.00 sec)

  (2)# 2.左lete join 左链接:在内连接的基础上保留左表没有的对应关系的记录

select *from emp left join dep on emp.dep_id = dep.id;
        mysql> select *from emp left join dep on emp.dep_id = dep.id;
        +----+-------+--------+------+--------+------+--------------+
        | id | name  | sex    | age  | dep_id | id   | name         |
        +----+-------+--------+------+--------+------+--------------+
        |  1 | jason | male   |   18 |    200 |  200 | 技术         |
        |  5 | owen  | male   |   18 |    200 |  200 | 技术         |
        |  2 | egon  | female |   48 |    201 |  201 | 人力资源     |
        |  3 | kevin | male   |   38 |    201 |  201 | 人力资源     |
        |  4 | nick  | female |   28 |    202 |  202 | 销售         |
        |  6 | jerry | female |   18 |    204 | NULL | NULL         |
        +----+-------+--------+------+--------+------+--------------+

  (3)# 3.右链接: 在内连接的基础上保留左表没有对应关系的记录

    select * from emp rigth join dep on emp.dep_id=dep.id;
        
        
        mysql> select *from emp left join dep on emp.dep_id = dep.id;
        +----+-------+--------+------+--------+------+--------------+
        | id | name  | sex    | age  | dep_id | id   | name         |
        +----+-------+--------+------+--------+------+--------------+
        |  1 | jason | male   |   18 |    200 |  200 | 技术         |
        |  5 | owen  | male   |   18 |    200 |  200 | 技术         |
        |  2 | egon  | female |   48 |    201 |  201 | 人力资源     |
        |  3 | kevin | male   |   38 |    201 |  201 | 人力资源     |
        |  4 | nick  | female |   28 |    202 |  202 | 销售         |
        |  6 | jerry | female |   18 |    204 | NULL | NULL         |
        +----+-------+--------+------+--------+------+--------------+

 

  (4)# 4.全连接:在内连接的基础上保留 左 右 表中没有的对应关系的记录

select * from emp left join dep on emp.dep_id = dep.id
        union
        select * from emp right join dep on emp.dep_id = dep.id;
            
        mysql> select * from emp left join dep on emp.dep_id = dep.id
    -> union
    -> select * from emp right join dep on emp.dep_id = dep.id;
        +------+-------+--------+------+--------+------+--------------+
        | id   | name  | sex    | age  | dep_id | id   | name         |
        +------+-------+--------+------+--------+------+--------------+
        |    1 | jason | male   |   18 |    200 |  200 | 技术         |
        |    5 | owen  | male   |   18 |    200 |  200 | 技术         |
        |    2 | egon  | female |   48 |    201 |  201 | 人力资源     |
        |    3 | kevin | male   |   38 |    201 |  201 | 人力资源     |
        |    4 | nick  | female |   28 |    202 |  202 | 销售         |
        |    6 | jerry | female |   18 |    204 | NULL | NULL         |
        | NULL | NULL  | NULL   | NULL |   NULL |  203 | 运营         |
        +------+-------+--------+------+--------+------+--------------+

三.子查询

  # 就是一个查询=语句用括号括起来当作另一个查询语句的条件去用
  如:

  # 1.查询部门是技术或者人力资源的员工信息

先获取技术部和人力资源部的id号,再去员工表里面根据前面的id筛选出符合要求的员工信息
"""
select * from emp where dep_id in (select id from dep where name = "技术" or name = "人力资源");

  # 2.每个部门最新入职的员工 思路:先查每个部门最新入职的员工,再按部门对应上联表查询

select t1.id,t1.name,t1.hire_date,t1.post,t2.* from emp as t1
inner join
(select post,max(hire_date) as max_date from emp group by post) as t2
on t1.post = t2.post
where t1.hire_date = t2.max_date
;

"""
记住一个规律,表的查询结果可以作为其他表的查询条件,也可以通过其别名的方式把它作为一张虚拟表去跟其他表做关联查询
"""

以上是关于MySQL之表查询的主要内容,如果未能解决你的问题,请参考以下文章

Python学习之旅—Mysql数据库之表操作(where+group by+having+order by)

MySQL之表操作

数据库之表查询,单表多表,子查询

mysql之表分区

6.MySQL优化---高级进阶之表的设计及优化

Django之表高级操作