当前位置:首页>笔记分享>MySQL笔记>MySQL基础以及单表查询

MySQL基础以及单表查询

1、数据库的基本概念

1.1、数据库:

​ 英文单词DataBase,简称DB。按照一定格式存储数据的一些文件的组合。
​ 顾名思义:存储数据的仓库,实际上就是一堆文件。这些文件中存储了
​ 具有特定格式的数据。

1.2、数据库管理系统:

  • DataBaseManagement,简称DBMS。

  • 数据库管理系统是专门用来管理数据库中数据的,数据库管理系统可以对数据库当中的数据进行增删改查。

  • 常见的数据库管理系统:

    • MySQL、Oracle、MS SqlServer、DB2、sybase等....

1.3、SQL:结构化查询语言

程序员需要学习SQL语句,程序员通过编写SQL语句,然后DBMS负责执行SQL语句,最终来完成数据库中数据的增删改查操作。

SQL是一套标准,程序员主要学习的就是SQL语句,这个SQL在mysql中可以使用,

同时在Oracle中也可以使用,在DB2中也可以使用。

1.4、三者之间的关系?

DBMS--执行--> SQL --操作--> DB

DBMS执行SQL语句操作数据

先安装数据库管理系统MySQL,然后学习SQL语句怎么写,编写SQL语句之后,DBMS
对SQL语句进行执行,最终来完成数据库的数据管理。

2、安装MySQL数据库管理系统。

2.1、win系统

第一步:先安装,选择“经典版”

第二步:需要进行MySQL数据库实例配置。

注意:一路下一步就行了!!!!!

需要注意的事项?

  • 端口号:
    • 端口号port是任何一个软件/应用都会有的,端口号是应用的唯一代表。
    • 端口号通常和IP地址在一块,IP地址用来定位计算机的,端口号port
    • 是用来定位计算机上某个服务的/某个应用的!
    • 在同一台计算机上,端口号不能重复。具有唯一性。

mysql数据库启动的时候,这个服务占有的默认端口号是3306
这是大家都知道的事儿。记住。

  • 字符编码方式?
    设置mysql数据库的字符编码方式为 UTF8
    一定要注意:先选中第3个单选按钮,然后再选择utf8字符集。
  • 服务名称?
    默认是:MySQL
    不用改。
  • 选择配置环境变量path:
    如果没有选择怎么办?你可以手动配置
    path=其它路径;C:\Program Files (x86)\MySQL\MySQL Server 5.5\bin
  • mysql超级管理员用户名不能改,一定是:root
    • 你需要设置mysql数据库超级管理员的密码。
    • 我们设置为123456
  • 设置密码的同时,可以激活root账户远程访问。
    • 激活:表示root账号可以在外地登录。
    • 不激活:表示root账号只能在本机上使用。我这里选择激活了!

2.1、mac系统

  1. https://dev.mysql.com/downloads/mysql/ 下载安装包 一路next
  2. 系统偏好设置中会有MySQL图标,点进去可以设置启停
  3. 在终端加入环境路径
    1. 如果是bash,执行open ~/.bash_profile;如果是zsh,执行open ~/.zshrc
    2. 添加语句PATH=$PATH:/usr/local/mysql/bin,保存
    3. 立即生效,source ~/.bash_profile or source ~/.zshrc
  4. 登录mysql mysql -uroot -p

3、MySQL数据库的完美卸载!

​ 第一步:双击安装包进行卸载删除。
​ 第二步:删除目录:
​ 把C:\ProgramData下面的MySQL目录干掉。
​ 把C:\Program Files (x86)下面的MySQL目录干掉。

这样就卸载结束了!

4、找MySQL的服务在哪里?

计算机-->右键-->管理-->服务和应用程序-->服务-->找mysql服务

MySQL的服务,默认是“启动”的状态,只有启动了mysql才能用。

默认情况下是“自动”启动,自动启动表示下一次重启操作系统的时候自动启动该服务。

  • 可以在服务上点击右键:

    • 启动
    • 重启服务
    • 停止服务...
  • 还可以改变服务的默认配置:服务上点击右键,属性,然后可以选择启动方式:

    • 自动(延迟启动)
    • 自动
    • 手动
    • 禁用

5、启动和关闭mysql服务呢?

语法:

  • net stop 服务名称;
  • net start 服务名称;

其它服务的启停都可以采用以上的命令。

6、登录mysql数据库呢?

mysql安装了,服务启动了,怎么使用客户端

使用bin目录下的mysql.exe命令来连接mysql数据库服务器

#本地登录(显示编写密码的形式):
    C:\Users\Administrator>mysql -uroot -p12345678
#本地登录(隐藏密码的形式):
    C:\Users\Administrator>mysql -uroot -p

7、mysql常用命令:

不区分大小写,不见分号不执行,\c用来终止一条命令的输入

  • 退出exit
  • 查看数据库show databases;
  • 使用数据库use 数据库名
  • 查看数据库下有那些表show tables
  • 创建数据库create database 数据库名;
  • 查看数据库版本select version();
  • 查看当前用的那个数据库select database();

8、数据库当中最基本的单元是表:table

  • 什么是表table?为什么用表来存储数据呢?
    • 数据库当中是以表格的形式表示数据的。因为表比较直观。
  • 任何一张表都有行和列:
    • 行(row):被称为数据/记录。
    • 列(column):被称为字段。
  • 每一个字段都有:字段名、数据类型、约束等属性。
    • 字段名可以理解,是一个普通的名字,见名知意就行。
    • 数据类型:字符串,数字,日期等,后期讲。
    • 约束:约束也有很多,其中一个叫做唯一性约束,这种约束添加之后,该字段中的数据不能重复。

9、关于SQL语句的分类?

SQL语句有很多,最好进行分门别类,这样更容易记忆。

  • DQL:数据查询语言(凡是带有select关键字的都是查询语句)
    • 包含select...的都是
  • DML:数据操作语言(凡是对表当中的数据进行增删改的都是DML)
    • insert delete update 增删改
    • 这个主要是操作表中的数据data。
  • DDL:数据定义语言
    • 凡是带有create、drop、alter的都是DDL。DDL主要操作的是表的结构。不是表中的数据。
    • create:新建,等同于增,drop:删除,alter:修改
    • 这个增删改和DML不同,这个主要是对表结构进行操作。
  • TCL:是事务控制语言
    • 事务提交:commit;
    • 事务回滚:rollback;
  • DCL:是数据控制语言。
    • 例如:授权grant、撤销权限revoke....

10、导入提前准备好的数据:

bjpowernode.sql 这个文件中是我提前为大家练习准备的数据库表。
怎么将sql文件中的数据导入呢?
mysql> source D:\course\03-MySQL\document\bjpowernode.sql

    注意:路径中不要有中文!!!!

11.简单查询语句

  • 查看表中数据select * from 表名 表示从表中查所有数据
    • 效率低,可读性差,开发过程 不建议使用
  • 查看表的结构,不看数据只看结构desc 表名; desc是describe的缩写
  • 查询一个字段select 字段名 from 表名;
  • 查询两个字段,或者多个字段,使用逗号隔开“,” 如select deptno,dname from dept;
  • 查询所有字段,可以用*号或者将所有字段名用逗号隔开。(建议写出所有字段)
  • 给查询的列起别名select 字段名(列名)as 别名 from 表名 利用as实现,只是将显示更改,原表不变

强调:1.对于SQL语句来说,是通用的,所有的SQL语句以“;”结尾。另外SQL语句不区分大小写,都行。

2.select语句永远不会做修改操作,只负责查询,检索

3.起别名可以省略as,别名中有空格则需要加单引号将别名包起来,数据库字符串用单引号,双引号oracle识别不了,别名是中文也要单引号括起来

4.字段可以使用数学表达式,比如给员工工资*12

12、条件查询

12.1、什么是条件查询?

不是将表中所有数据都查出来。是查询出来符合条件的。
语法格式:

select
            字段1,字段2,字段3....
from 
            表名
where
            条件;

12.2、查询条件?

= 等于

  • 查询薪资等于800的员工姓名和编号

    • select empno,ename from emp where sal = 800;`
  • 查询SMITH的编号和薪资?

    • select empno,sal from emp where ename = 'SMITH'; //字符串使用单引号

<>或!= 不等于

< 小于

<= 小于等于

大于>

大于等于>=

between ⋯ and ⋯.

  • 两个值之间, 等同于 >= and <= (闭区间包含两边的值,左小右大)

  • 例:select ename,empno from emp where sal between 2450 and 3000;

is null 为 null(is not null 不为空)

例:select ename,empno,sal from emp where comm is null 查询谁的补助是null 不能=

sql中null不能用=号衡量

and 并且

查询工作岗位是MANAGER并且工资大于2500的员工信息?

select 
        empno,ename,job,sal 
    from 
        emp 
    where 
        job = 'MANAGER' and sal > 2500;

or 或者

查询工作岗位是MANAGER和SALESMAN的员工?

select empno,ename,job from emp where job = 'MANAGER';
select empno,ename,job from emp where job = 'SALESMAN';
select 
    empno,ename,job
from
    emp
where 
    job = 'MANAGER' or job = 'SALESMAN';

and优先级比or高 要注意,可以加小括号

in 包含,

相当于多个 or (not in 不在这个范围中)

  • 查询工作岗位是MANAGER和SALESMAN的员工?
    select empno,ename,job from emp where job = 'MANAGER' or job = 'SALESMAN';
    select empno,ename,job from emp where job in('MANAGER', 'SALESMAN');

注意:in不是一个区间。in后面跟的是具体的值。

like 称为模糊查询

  • 支持%或下划线匹配

  • %匹配任意多个字符

  • 下划线:任意一个字符。(%是一个特殊的符号,_ 也是一个特殊符号)

#找出名字中含有O的?
    mysql> select ename from emp where ename like '%O%';
    +-------+
    | ename |
    +-------+
    | JONES |
    | SCOTT |
    | FORD  |
    +-------+

#找出名字以T结尾的?
        select ename from emp where ename like '%T';
#找出名字以K开始的?
        select ename from emp where ename like 'K%';
#找出第二个字每是A的?
        select ename from emp where ename like '_A%';
#找出第三个字母是R的?
        select ename from emp where ename like '__R%';

#例如有这个表
    t_student学生表
    name字段
    ----------------------
    zhangsan
    lisi
    wangwu
    zhaoliu
    jack_son
#找出名字中有“_”的?
        select name from t_student where name like '%_%'; #这样不行。下划线有特殊含义

        select name from t_student where name like '%\_%'; #\转义字符。
        +----------+
        | name     |
        +----------+
        | jack_son |
        +----------+

13、排序

13.1、按单字段排序

#按薪资排序
select 
        ename,sal
    from
        emp
    order by
        sal desc; // 默认是升序!!! 加desc是降序

降序 加desc 升序asc默认的

+--------+---------+
| ename  | sal     |
+--------+---------+
| KING   | 5000.00 |
| SCOTT  | 3000.00 |
| FORD   | 3000.00 |
| JONES  | 2975.00 |
| BLAKE  | 2850.00 |
| CLARK  | 2450.00 |
| ALLEN  | 1600.00 |
| TURNER | 1500.00 |
| MILLER | 1300.00 |
| MARTIN | 1250.00 |
| WARD   | 1250.00 |
| ADAMS  | 1100.00 |
| JAMES  |  950.00 |
| SMITH  |  800.00 |
+--------+---------+

13.2、多个字段排序

例如:查询员工名字和薪资,要求按照薪资升序,如果薪资一样的话,再按照名字升序排列。

select 
        ename,sal
from
        emp
order by
        sal asc, ename asc; #sal在前,起主导,只有sal相等的时候,才会考虑启用ename排序。

13.3、根据字段的位置也可以排序

select ename,sal from emp order by 2; 2表示第二列。第二列是sal
按照查询结果的第2列sal排序。

了解一下,不建议在开发中这样写,因为不健壮。因为列的顺序很容易发生改变,列顺序修改之后,2就废了。

13.4、综合一点的案例:

找出工资在1250到3000之间的员工信息,要求按照薪资降序排列。

select 
        ename,sal
from
        emp
where
        sal between 1250 and 3000
order by
        sal desc;
#-------------------------
#关键字顺序不能变:
    select
        ...
    from
        ...
    where
        ...
    order by
        ...
#以上语句的执行顺序必须掌握:
        #第一步:from
        #第二步:where
        #第三步:select
        #第四步:order by(排序总是在最后执行!)

14、数据处理函数

数据处理函数又被称为单行处理函数

  • 单行处理函数的特点:一个输入对应一个输出。(一行一行处理的)

  • 和单行处理函数相对的是:多行处理函数。(多行处理函数特点:多个输入,对应1个输出!)(一次处理多行)

n个输入对应n个输出就是单行处理特点

14.1、常见的单行处理函数

函数 描述
lower 转换小写
upper 转换大写
substr(被截取子串,起始下标,截取长度) 取子串(起始下标从1开始)
length 取长度
trim 去空格
str_to_date 将字符串转换成日期
date_format 格式化日期
format 设置千分位
round 四舍五入
rand() 生成随机数
ifnull 可以将null转换成具体值
concat 字符串拼接
case..when..then..when..then..else..end 当什么时候怎么做,其他时候怎么做

代码演示:

#lower 转换小写
mysql> select lower(ename) as ename from emp;
#14个输入,最后还是14个输出。这是单行处理函数的特点。

#upper 转换大写
mysql> select upper(name) as name from t_student;

#substr 取子串(substr( 被截取的字符串, 起始下标,截取的长度))
select substr(ename, 1, 1) as ename from emp;
#注意:起始下标从1开始,没有0.

#找出员工名字第一个字母是A的员工信息?
        #第一种方式:模糊查询
            select ename from emp where ename like 'A%';
        #第二种方式:substr函数
            select 
                ename 
            from 
                emp 
            where 
                substr(ename,1,1) = 'A';

#首字母大写?
        select concat(upper(substr(name,1,1)),substr(name,2,length(name) - 1)) as result from       

#concat函数进行字符串的拼接
    select concat(empno,ename) from emp;

#length 取长度
    select length(ename) enamelength from emp;

#trim 去空格
    mysql> select * from emp where ename = '  KING';
    Empty set (0.00 sec)

    mysql> select * from emp where  ename = trim('   KING');
    +-------+-------+-----------+------+------------+---------+------+--------+
    | EMPNO | ENAME | JOB       | MGR  | HIREDATE   | SAL     | COMM | DEPTNO |
    +-------+-------+-----------+------+------------+---------+------+--------+
    |  7839 | KING  | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL |     10 |
    +-------+-------+-----------+------+------------+---------+------+--------+
#---------------------------------------------------------------------------------
#str_to_date 将字符串转换成日期 (后面单独说)
#date_format 格式化日期
#format 设置千分位

#case..when..then..when..then..else..end
#当员工的工作岗位是MANAGER的时候,工资上调10%,当工作岗位是SALESMAN的时候,工资上调50%,其它正常。
#(注意:不修改数据库,只是将查询结果显示为工资上调)
    select 
        ename,
        job, 
        sal as oldsal,
        (case job when 'MANAGER' then sal*1.1 when 'SALESMAN' then sal*1.5 else sal end) as newsal 
    from 
        emp; 

    +--------+-----------+---------+---------+
    | ename  | job       | oldsal  | newsal  |
    +--------+-----------+---------+---------+
    | SMITH  | CLERK     |  800.00 |  800.00 |
    | ALLEN  | SALESMAN  | 1600.00 | 2400.00 |
    | WARD   | SALESMAN  | 1250.00 | 1875.00 |
    | JONES  | MANAGER   | 2975.00 | 3272.50 |
    | MARTIN | SALESMAN  | 1250.00 | 1875.00 |
    | BLAKE  | MANAGER   | 2850.00 | 3135.00 |
    | CLARK  | MANAGER   | 2450.00 | 2695.00 |
    | SCOTT  | ANALYST   | 3000.00 | 3000.00 |
    | KING   | PRESIDENT | 5000.00 | 5000.00 |
    | TURNER | SALESMAN  | 1500.00 | 2250.00 |
    | ADAMS  | CLERK     | 1100.00 | 1100.00 |
    | JAMES  | CLERK     |  950.00 |  950.00 |
    | FORD   | ANALYST   | 3000.00 | 3000.00 |
    | MILLER | CLERK     | 1300.00 | 1300.00 |
    +--------+-----------+---------+---------+

#round 四舍五入
    select 字段 from 表名;
    select ename from emp;
    select 'abc' from emp; // select后面直接跟“字面量/字面值”

    mysql> select 'abc' as bieming from emp;
    +---------+
    | bieming |
    +---------+
    | abc     |
    | abc     |
    | abc     |
    | abc     |
    | abc     |
    | abc     |
    | abc     |
    | abc     |
    | abc     |
    | abc     |
    | abc     |
    | abc     |
    | abc     |
    | abc     |
    +---------+

    mysql> select abc from emp;
    ERROR 1054 (42S22): Unknown column 'abc' in 'field list'
    #这样肯定报错,因为会把abc当做一个字段的名字,去emp表中找abc字段去了。

    select 1000 as num from emp; // 1000 也是被当做一个字面量/字面值。
    +------+
    | num  |
    +------+
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    +------+

#结论:select后面可以跟某个表的字段名(可以等同看做变量名),也可以跟字面量/字面值(数据)。

    select round(1236.567, 1) as result from emp; //保留1个小数
    select round(1236.567, 2) as result from emp; //保留2个小数
    select round(1236.567, -1) as result from emp; // 保留到十位
    select round(1236.567, -2) as result from emp;

#rand() 生成随机数
    mysql> select round(rand()*100,0) from emp; // 100以内的随机数

#ifnull 可以将 null 转换成一个具体值
#ifnull是空处理函数。专门处理空的。
#在所有数据库当中,只要有NULL参与的数学运算,最终结果就是NULL。
    mysql> select ename, sal + comm as salcomm from emp;
#计算每个员工的年薪?年薪 = (月薪 + 月补助) * 12
        select ename, (sal + comm) * 12 as yearsal from emp;
#注意:NULL只要参与运算,最终结果一定是NULL。为了避免这个现象,需要使用ifnull函数。
#ifnull函数用法:ifnull(数据, 被当做哪个值)
#如果“数据”为NULL的时候,把这个数据结构当做哪个值。
#补助为NULL的时候,将补助当做0
select ename, (sal + ifnull(comm, 0)) * 12 as yearsal from emp;

1.在所有数据库当中,只要有NULL参与的数学运算,最终结果就是NULL。

2.ifnull函数用法:ifnull(数据, 被当做哪个值)

3.select后面可以跟某个表的字段名(可以等同看做变量名),也可以跟字面量/字面值(数据)。

14.2、分组函数(多行处理函数)

多行处理函数的特点:输入多行,最终输出一行。

函数 描述
count 计数
sum 求和
avg 平均数
max 最大值
min 最小值

注意:分组函数在使用的时候必须先进行分组,然后才能用。如果你没有对数据进行分组,整张表默认为一组。

#找出最高工资?
    mysql> select max(sal) from emp;
    +----------+
    | max(sal) |
    +----------+
    |  5000.00 |
    +----------+

#找出最低工资?
    mysql> select min(sal) from emp;
    +----------+
    | min(sal) |
    +----------+
    |   800.00 |
    +----------+

#计算工资和:
    mysql> select sum(sal) from emp;
    +----------+
    | sum(sal) |
    +----------+
    | 29025.00 |
    +----------+

#计算平均工资:
    mysql> select avg(sal) from emp;
    +-------------+
    | avg(sal)    |
    +-------------+
    | 2073.214286 |
    +-------------+
#14个工资全部加起来,然后除以14。

#计算员工数量?
    mysql> select count(ename) from emp;
    +--------------+
    | count(ename) |
    +--------------+
    |           14 |
    +--------------+

#分组函数在使用的时候需要注意哪些?
#第一点:分组函数自动忽略NULL,你不需要提前对NULL进行处理。
    mysql> select sum(comm) from emp;
    +-----------+
    | sum(comm) |
    +-----------+
    |   2200.00 |
    +-----------+

    mysql> select count(comm) from emp;
    +-------------+
    | count(comm) |
    +-------------+
    |           4 |
    +-------------+
    mysql> select avg(comm) from emp;
    +------------+
    | avg(comm)  |
    +------------+
    | 550.000000 |
    +------------+

#第二点:分组函数中count(*)和count(具体字段)有什么区别?
        mysql> select count(*) from emp;
        +----------+
        | count(*) |
        +----------+
        |       14 |
        +----------+

        mysql> select count(comm) from emp;
        +-------------+
        | count(comm) |
        +-------------+
        |           4 |
        +-------------+

#count(具体字段):表示统计该字段下所有不为NULL的元素的总数。
#count(*):统计表当中的总行数。(只要有一行数据count则++)
#因为每一行记录不可能都为NULL,一行数据中有一列不为NULL,则这行数据就是有效的。

#第三点:分组函数不能够直接使用在where子句中。
#找出比最低工资高的员工信息。
select ename,sal from emp where sal > min(sal);
#表面上没问题,运行一下?
                ERROR 1111 (HY000): Invalid use of group function
    ?????????????????????????????????????????????????????????????????????
#说完分组查询(group by)之后就明白了了。

#第四点:所有的分组函数可以组合起来一起用。
        select sum(sal),min(sal),max(sal),avg(sal),count(*) from emp;
        +----------+----------+----------+-------------+----------+
        | sum(sal) | min(sal) | max(sal) | avg(sal)    | count(*) |
        +----------+----------+----------+-------------+----------+
        | 29025.00 |   800.00 |  5000.00 | 2073.214286 |       14 |
        +----------+----------+----------+-------------+----------+

注意1.分组函数自动忽略NULL,你不需要提前对NULL进行处理。

2.分组函数中count(*)和count(具体字段)区别

​ count(具体字段):表示统计该字段下所有不为NULL的元素的总数。

​ count(*):统计表当中的总行数。(只要有 一行数据count则++)

​ 因为每一行记录不可能都为NULL,一行数据中有一列不为NULL,则这行数据就是有效的。

3.分组函数不能够直接使用在where子句中。

4.所有的分组函数可以组合起来一起用。

14.3、分组查询(非常重要:五颗星*****)

什么是分组查询?

在实际的应用中,可能有这样的需求,需要先进行分组,然后对每一组的数据进行操作。

这个时候我们需要使用分组查询,怎么进行分组查询呢?

语法:

select
            ...
from
            ...
group by 
            ...
#计算每个部门的工资和?
#计算每个工作岗位的平均薪资?
#找出每个工作岗位的最高薪资?
    ....

#将之前的关键字全部组合在一起,来看一下他们的执行顺序?
    select
        ...
    from
        ...
    where
        ...
    group by
        ...
    order by
        ...

以上关键字的顺序不能颠倒,需要记忆。执行顺序是什么?
        1. from
        2. where
        3. group by
        4. select
        5. order by

为什么分组函数不能直接使用在where后面?因为分组函数在使用的时候必须先分组之后才能使用。where执行的时候,还没有分组。所以where后面不能出现分组函数。

找出每个工作岗位的工资和?
实现思路:按照工作岗位分组,然后对工资求和。

        select 
            job,sum(sal)
        from
            emp
        group by
            job;

        +-----------+----------+
        | job       | sum(sal) |
        +-----------+----------+
        | ANALYST   |  6000.00 |
        | CLERK     |  4150.00 |
        | MANAGER   |  8275.00 |
        | PRESIDENT |  5000.00 |
        | SALESMAN  |  5600.00 |
        +-----------+----------+
#以上这个语句的执行顺序?先从emp表中查询数据。根据job字段进行分组。然后对每一组的数据进行sum(sal)

    select ename,job,sum(sal) from emp group by job;
    +-------+-----------+----------+
    | ename | job       | sum(sal) |
    +-------+-----------+----------+
    | SCOTT | ANALYST   |  6000.00 |
    | SMITH | CLERK     |  4150.00 |
    | JONES | MANAGER   |  8275.00 |
    | KING  | PRESIDENT |  5000.00 |
    | ALLEN | SALESMAN  |  5600.00 |
    +-------+-----------+----------+
#以上语句在mysql中可以执行,但是毫无意义。以上语句在oracle中执行报错。oracle的语法比mysql的语法严格。(mysql的语法相对来说松散一些!)

重点结论:在一条select语句当中,如果有group by语句的话,select后面只能跟:参加分组的字段,以及分组函数。其它的一律不能跟。

找出每个部门的最高薪资
实现思路:按照部门编号分组,求每一组的最大值。

#select后面添加ename字段没有意义,另外oracle会报错。
        mysql> select ename,deptno,max(sal) from emp group by deptno;
        +-------+--------+----------+
        | ename | deptno | max(sal) |
        +-------+--------+----------+
        | CLARK |     10 |  5000.00 |
        | SMITH |     20 |  3000.00 |
        | ALLEN |     30 |  2850.00 |
        +-------+--------+----------+
#规范
        mysql> select deptno,max(sal) from emp group by deptno;
        +--------+----------+
        | deptno | max(sal) |
        +--------+----------+
        |     10 |  5000.00 |
        |     20 |  3000.00 |
        |     30 |  2850.00 |
        +--------+----------+

找出“每个部门,不同工作岗位”的最高薪资?

    +--------+-----------+---------+--------+
    | ename  | job       | sal     | deptno |
    +--------+-----------+---------+--------+
    | MILLER | CLERK     | 1300.00 |     10 |
    | KING   | PRESIDENT | 5000.00 |     10 |
    | CLARK  | MANAGER   | 2450.00 |     10 |
    | FORD   | ANALYST   | 3000.00 |     20 |
    | ADAMS  | CLERK     | 1100.00 |     20 |
    | SCOTT  | ANALYST   | 3000.00 |     20 |
    | JONES  | MANAGER   | 2975.00 |     20 |
    | SMITH  | CLERK     |  800.00 |     20 |
    | BLAKE  | MANAGER   | 2850.00 |     30 |
    | MARTIN | SALESMAN  | 1250.00 |     30 |
    | ALLEN  | SALESMAN  | 1600.00 |     30 |
    | TURNER | SALESMAN  | 1500.00 |     30 |
    | WARD   | SALESMAN  | 1250.00 |     30 |
    | JAMES  | CLERK     |  950.00 |     30 |
    +--------+-----------+---------+--------+
    #技巧:两个字段联合成1个字段看。(两个字段联合分组)
    select 
        deptno, job, max(sal)
    from
        emp
    group by
        deptno, jo b;
    +--------+-----------+----------+
    | deptno | job       | max(sal) |
    +--------+-----------+----------+
    |     10 | CLERK     |  1300.00 |
    |     10 | MANAGER   |  2450.00 |
    |     10 | PRESIDENT |  5000.00 |
    |     20 | ANALYST   |  3000.00 |
    |     20 | CLERK     |  1100.00 |
    |     20 | MANAGER   |  2975.00 |
    |     30 | CLERK     |   950.00 |
    |     30 | MANAGER   |  2850.00 |
    |     30 | SALESMAN  |  1600.00 |
    +--------+-----------+----------+

技巧:两个字段联合成1个字段看。(两个字段联合分组)

使用having可以对分完组之后的数据进一步过滤。

  • having不能单独使用,having不能代替where,having必须和group by联合使用。
#找出每个部门最高薪资,要求显示最高薪资大于3000的?
#第一步:找出每个部门最高薪资,按照部门编号分组,求每一组最大值。
        select deptno,max(sal) from emp group by deptno;
        +--------+----------+
        | deptno | max(sal) |
        +--------+----------+
        |     10 |  5000.00 |
        |     20 |  3000.00 |
        |     30 |  2850.00 |
        +--------+----------+

#第二步:要求显示最高薪资大于3000
        select 
            deptno,max(sal) 
        from 
            emp 
        group by 
            deptno
        having
            max(sal) > 3000;

        +--------+----------+
        | deptno | max(sal) |
        +--------+----------+
        |     10 |  5000.00 |
        +--------+----------+

思考一个问题:以上的sql语句执行效率是不是低?比较低,实际上可以这样考虑:先将大于3000的都找出来,然后再分组。

        select 
            deptno,max(sal)
        from
            emp
        where
            sal > 3000
        group by
            deptno;

        +--------+----------+
        | deptno | max(sal) |
        +--------+----------+
        |     10 |  5000.00 |
        +--------+----------+

优化策略:where和having,优先选择where,where实在完成不了了,再选择having。

where没办法的

where没办法用分组函数,因为where在分组之前执行

#找出每个部门平均薪资,要求显示平均薪资高于2500的。

#第一步:找出每个部门平均薪资
            select deptno,avg(sal) from emp group by deptno;
            +--------+-------------+
            | deptno | avg(sal)    |
            +--------+-------------+
            |     10 | 2916.666667 |
            |     20 | 2175.000000 |
            |     30 | 1566.666667 |
            +--------+-------------+

#第二步:要求显示平均薪资高于2500的
            select 
                deptno,avg(sal) 
            from 
                emp 
            group by 
                deptno
            having
                avg(sal) > 2500;

        +--------+-------------+
        | deptno | avg(sal)    |
        +--------+-------------+
        |     10 | 2916.666667 |
        +--------+-------------+

15、大总结(单表的查询学完了)

    select 
        ...
    from
        ...
    where
        ...
    group by
        ...
    having
        ...
    order by
        ...
以上关键字只能按照这个顺序来,不能颠倒。

执行顺序?
    1. from
    2. where
    3. group by
    4. having
    5. select
    6. order by

#从某张表中查询数据,
#先经过where条件筛选出有价值的数据。
#对这些有价值的数据进行分组。
#分组之后可以使用having继续筛选。
#select查询出来。
#最后排序输出!

执行顺序从某张表中查询数据,先经过where条件筛选出有价值的数据。对这些有价值的数据进行分组。分组之后可以使用having继续筛选。select查询出来。最后排序输出!

最后一个问题:找出每个岗位的平均薪资,要求显示平均薪资大于1500的,除MANAGER岗位之外,要求按照平均薪资降序排。

    select 
        job, avg(sal) as avgsal
    from
        emp
    where
        job <> 'MANAGER'
    group by
        job
    having
        avg(sal) > 1500
    order by
        avgsal desc;
#输出
    +-----------+-------------+
    | job       | avgsal      |
    +-----------+-------------+
    | PRESIDENT | 5000.000000 |
    | ANALYST   | 3000.000000 |
    +-----------+-------------+

给TA打赏
共{{data.count}}人
人已打赏
Python基础Python笔记

Python元组与集合

2021-9-27 15:23:03

MySQL笔记

MySQL多表查询(增删改查)

2021-12-2 16:44:07

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
购物车
优惠劵
有新私信 私信列表
搜索