MySQL基础笔记原稿DAY1

MySQL基础笔记原稿Day1

链接命令

mysql -uroot -p

然后输入密码即可

语句输入控制

MySQL输入SQL语句时,不见;不会执行。只有输入;才会执行之前输入的所有语句。

若是不想执行已经输入的语句可以\c终止输入。此前输入的语句不会执行

显示全部表

show databases;

注意在MySQL中所有的指令都需要;,并且不区分大小写。链接命令不需要是因为还没有进入MySQL

使用某个数据库

use databaseName;

创建数据库

create database databaseName;

数据库中显示库内的全部表

show tables;

导入脚本数据

 source .sql文件位置

注意:此处需要绝对地址并且不能有中文

也可以通过这个脚本来导入

show databeses;
use bjpowernode;

create table dept(  
	deptno int(10) primary key,  
	dname varchar(14),  
	loc varchar(13));  

create table salgrade(  
	grade int(11), 
	 losal int(11), 
	 hisal int(11)  );  

create table emp(  
	empno int(4) primary key, 
	ename varchar(10), 
	job varchar(9),  
	mgr int(4),  
	hiredate date, 
	sal double(7,2),  
	comm double(7,2),  
	deptno int(2)  ); 

#插入表中的数据

insert into dept(deptno,dname,loc) values(10,'ACCOUNTING','NEW YORK');
insert into dept(deptno,dname,loc) values(20,'RESEARCHING','DALLAS');
insert into dept(deptno,dname,loc) values(30,'SALES','CHICAGO');
insert into dept(deptno,dname,loc) values(40,'OPERATIONS','BOSTON');

insert into salgrade(grade,losal,hisal) values(1,700,1200);
insert into salgrade(grade,losal,hisal) values(2,1201,1400);
insert into salgrade(grade,losal,hisal) values(3,1401,2000);
insert into salgrade(grade,losal,hisal) values(4,2001,3000);
insert into salgrade(grade,losal,hisal) values(5,3001,5000); 

insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7369,'SIMITH','CLERK',7902,'1980-12-17',800,null,20);
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7566,'JONES','MANAGER',7839,'1981-04-02',2975,null,20);
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,null,30);
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,null,10);
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,null,20);
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7839,'KING','PRESIDENT',null,'1981-11-17',5000,null,10);
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,null,30);
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,null,20);
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7900,'JAMES','CLERK',7698,'1981-12-03',950,null,30);
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7902,'FORD','ANALYST',7566,'1981-12-03',3000,null,20);
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7934,'MILLER','CLERK',7782,'1982-01-23',1300,null,10); 

select * from dept;select * from salgrade;select * from emp;

导入后表单如下:

+-----------------------+
| Tables_in_bjpowernode |
+-----------------------+
| dept  //部门表		 |
| emp   //员工表        |
| salgrade  //工资等级表|
+-----------------------+

+--------+-------------+----------+
| deptno | dname       | loc      |
+--------+-------------+----------+
|     10 | ACCOUNTING  | NEW YORK |
|     20 | RESEARCHING | DALLAS   |
|     30 | SALES       | CHICAGO  |
|     40 | OPERATIONS  | BOSTON   |
+--------+-------------+----------+

+-------+-------+-------+
| grade | losal | hisal |
+-------+-------+-------+
|     1 |   700 |  1200 |
|     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |
|     5 |  3001 |  5000 |
+-------+-------+-------+

+-------+--------+-----------+------+------------+---------+---------+--------+
| empno | ename  | job       | mgr  | hiredate   | sal     | comm    | deptno |
+-------+--------+-----------+------+------------+---------+---------+--------+
|  7369 | SIMITH | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20 |
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    NULL |     30 |
|  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |
+-------+--------+-----------+------+------------+---------+---------+--------+

其中dep为部门表

emp为员工表

salgrade为工资等级表

查看表中数据

select * from tableName;

那么就会得到上面的那个全部表中数据

而如果我们用

desc tableName;

那么将会得到

+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| deptno | int         | NO   | PRI | NULL    |       |
| dname  | varchar(14) | YES  |     | NULL    |       |
| loc    | varchar(13) | YES  |     | NULL    |       |
+--------+-------------+------+-----+---------+-------+

这表示了整张表的结构

desc表示describe,描述,当然也可以用describe查询

简单查询表数据

select 字段名 from 表名;

例如:我要查询部门的名字,就可以直接:

select dname from dept;

结果:

+-------------+
| dname       |
+-------------+
| ACCOUNTING  |
| RESEARCHING |
| SALES       |
| OPERATIONS  |
+-------------+

那么若果我要查询两个甚至多个字段怎么办:

select deptno,dname from dept;

注意使用,隔开

当需要查询所有字段,就用*表示。在SQL语句中*可以表示所有。不过使用*实际上是系统自动将星号转换成所有字段名。因此效率较低、可读性差。追求性能时不要用

给查询的字段起别名

可以在查询时使用as关键字为某个字段起一个便于读懂的别名。这项操作不会影响到数据库中实际字段变化。

​ 注意:select语句只负责查询,是不会进行任何修改操作的

select deptno,dname as departmentName from dept;
//或
select deptno,dname departmentName from dept;
//或
select deptno,dname as 'department Name' from dept;//当别名中有空格时,用单引号括起来。SQL中最好用单引号而非双引号

结果如下:

| deptno | departmentName |
+--------+----------------+
|     10 | ACCOUNTING     |
|     20 | RESEARCHING    |
|     30 | SALES          |
|     40 | OPERATIONS     |
+--------+----------------+

除此之外,我们还可以对字段内的数据起别名。比如现在我要获取员工的年薪,但是数据库内只有月薪

select ename,sal*12 as yearSal from emp;
| ename  | yearSal  |
+--------+----------+
| SIMITH |  9600.00 |
| ALLEN  | 19200.00 |
| WARD   | 15000.00 |
| JONES  | 35700.00 |
| MARTIN | 15000.00 |
| BLAKE  | 34200.00 |
| CLARK  | 29400.00 |
| SCOTT  | 36000.00 |
| KING   | 60000.00 |
| TURNER | 18000.00 |
| ADAMS  | 13200.00 |
| JAMES  | 11400.00 |
| FORD   | 36000.00 |
| MILLER | 15600.00 |
+--------+----------+

perfect

最后重申一下,select不会对数据进行修改,只是影响了输入的结果,类似于障眼法

条件查询

简单查询往往只能查询某个字段中的全部数据,而我们经常只需要查询其中部分符合条件的数据。因此需要条件查询

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

条件表达式有很多,除了最通用的=、<、>、!=等,还有:

  • between… and…介于两者之间,等同于>=and <=

  • is null 是否为空

  • and 、or 并且和或者

  • in 包含相当于多个or

  • not 取非

  • like 模糊查询

  • % 匹配任意字符

  • 下划线 匹配一个字符

    基本判断符

    这个没啥好说的

    示例:查询薪资大于等于2000的员工姓名和编号

    select empno ,ename  from emp where sal>=2000;
    
    and和or

    直接看示例:查询薪资大于等于2000并且工作岗位为’manager’的员工

    select empno,ename from emp where sal>2000 and job='manager';
    

    或:查询工作岗位为manager或salesman的员工

    select empno,ename from emp where job='salesman' or job='manager';
    

    但是,当and和or同时出现,就有一个优先级的的问题

    示例:若我们现在要查询工资大于2500,并且部门编号为10或20的员工。

    如果我们这么写

    select empno,ename,sal, deptno from emp where deptno=10 or deptno=20 and  sal>2500 ;
    

    结果为:

    +-------+--------+---------+--------+
    | empno | ename  | sal     | deptno |
    +-------+--------+---------+--------+
    |  7369 | SIMITH |  800.00 |     20 |
    |  7566 | JONES  | 2975.00 |     20 |
    |  7788 | SCOTT  | 3000.00 |     20 |
    |  7839 | KING   | 5000.00 |     10 |
    |  7876 | ADAMS  | 1100.00 |     20 |
    |  7902 | FORD   | 3000.00 |     20 |
    +-------+--------+---------+--------+
    

    仔细对照,显然有很多部门编号为20的员工并不符合薪资大于2500的要求。所以上述这行命令执行起来等价于

    select empno,ename,sal, deptno from emp where deptno=10 or (deptno=20 and  sal>2500) ;
    

    这显然不是我们想要的,但是也证明了,实际上and的优先级是要高于or

    因此,为得到正确的结果,我们可以这样写:

    select empno,ename,sal, deptno from emp where (deptno=10 or deptno=20) and  sal>2500 ;
    

    正确结果为:

    +-------+-------+---------+--------+
    | empno | ename | sal     | deptno |
    +-------+-------+---------+--------+
    |  7566 | JONES | 2975.00 |     20 |
    |  7788 | SCOTT | 3000.00 |     20 |
    |  7839 | KING  | 5000.00 |     10 |
    |  7902 | FORD  | 3000.00 |     20 |
    +-------+-------+---------+--------+
    
    in

    in 表示包含,相当于多个or

    在上面的or中的示例里。我们查询了工作岗位为manager或salesman的员工

    这个问题也可以用in解决

    select empno,ename,job from emp where job in ('manager','salesman');
    

    注意:in后跟的是具体值,不能是区间,需要区间的会在between and里实现

    not

    取非,常用于isin中,比如is not nullnot in。比如上面那个例子的反面:

    select empno,ename,job from emp where job not in ('manager','salesman');
    
    like 模糊查询

    like支持%__匹配(可以理解为占位)

    %可以匹配任意多的字符,而下划线__只能匹配一个字符

    示例:找出员工中名字含有O

    select empno,ename,job from emp where ename like '%O%';
    
    +-------+-------+---------+
    | empno | ename | job     |
    +-------+-------+---------+
    |  7566 | JONES | MANAGER |
    |  7788 | SCOTT | ANALYST |
    |  7902 | FORD  | ANALYST |
    +-------+-------+---------+
    

    特别提示,对于'%O%',数据库会认为即便是以O开头或结尾也符合条件。

示例2:找出名字以T为结尾的员工

select empno,ename,job from emp where ename like '%T';
+-------+-------+---------+
| empno | ename | job     |
+-------+-------+---------+
|  7788 | SCOTT | ANALYST |
+-------+-------+---------+

特别提示:这时,名字中也有T但不是结尾的就无法通过筛选了。可以用正则表达式的理念进行理解

示例3:找出名字第二个字母为A的员工

select empno,ename,job from emp where ename like '_A%';

那么,假如现在表内某个人的名字中有下划线或是%,我们需要找出这些人,如何去做?

其实用转义字符\即可

select empno,ename,job from emp where ename like '%\_%';

条件查询结束

排序

order by 排序
select 
	ename,sal
from 
	emp
order by
	sal;
+--------+---------+
| ename  | sal     |
+--------+---------+
| SIMITH |  800.00 |
| JAMES  |  950.00 |
| ADAMS  | 1100.00 |
| WARD   | 1250.00 |
| MARTIN | 1250.00 |
| MILLER | 1300.00 |
| TURNER | 1500.00 |
| ALLEN  | 1600.00 |
| CLARK  | 2450.00 |
| BLAKE  | 2850.00 |
| JONES  | 2975.00 |
| SCOTT  | 3000.00 |
| FORD   | 3000.00 |
| KING   | 5000.00 |
+--------+---------+

显然,默认状态下,order by是一个升序排列。

若要人为限定升序或降序排列,我们只需要在order by后面的指定字段后加一个ascend(升序)或descend(降序)。通常简写为ascdesc

select ename,sal from emp order by sal desc;
+--------+---------+
| 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 |
| WARD   | 1250.00 |
| MARTIN | 1250.00 |
| ADAMS  | 1100.00 |
| JAMES  |  950.00 |
| SIMITH |  800.00 |
+--------+---------+

order by也可以同时按照两个甚至更多字段进行排序。但是会有优先级区别

比如下面这个示例:按照薪资升序排列,当薪资相同时,再按照名字升序排列

select 
	ename,sal 
from 
	emp 
order by 
	sal asc,ename asc;

综合案例:找出薪资在1250-3000之间的,要求按照薪资降序排列(当薪资相等时按名字升序排列)

select 
	ename,sal 
from 
	emp 
where
	sal between 1250 and 3000
order by 
	sal desc,ename asc;
| ename  | sal     |
+--------+---------+
| FORD   | 3000.00 |
| SCOTT  | 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 |
+--------+---------+

特别提醒:以上关键字书写顺序不能乱。但是关键字间的执行顺序并不是按照书写顺序排的。

执行顺序为:from、where、select、order by

数据处理函数

单行处理函数
  • 单行处理函数顾名思义,就一行。那么他的特点就是:一个输入对应一个输出

  • 多行处理函数:与单行相对应,多个输入,一个输出

    这里的输入,指的是数据库数据输入函数中。函数类似于java中的方法

    常见的单行处理函数:

    • lower 转小写
    • upper转大写
    • substr取子串
    • concat 字符串拼接
    • length取长度
    • trim去掉空格
    • str_to_date将字符串转换为日期
    • date_format 格式化日期
    • format设置千分位,格式
    • round四舍五入
    • rand生成随机数
    • ifnull将null转换为一个具体值
    • case …when …then …when …then …else …end

    前两个大小写的互换我们就不看了

    直接从substr开始

    substr

    substr(被截取的字符串,起始下标,截取的长度)

    示例:截取员工姓名首字母,并转换为小写字母

    select lower(substr(ename,1,1)) as firstletter from emp; 
    

    特别提醒:SQL语句下标从1开始,而非从0开始

    示例2:查询员工名字第一个字母为A的信息(要求不使用like模糊查询)

    select ename from emp where substr(ename,1,1)='A' ;
    
    concat

    示例:将员工姓名换成首字母大写其余字母小写输出

    select concat(upper(substr(ename,1,1)),lower(substr(ename,2,length(ename)-1))) from emp;
    

    这就顺便学了length

    trim

    我们在实际使用时,获取到的查询数据往往是混乱的,可能带有多余的空格比如:

    select * from emp where ename='   KING  ';
    

    结果:

    Empty set (0.00 sec)
    

    但是如果这样:

    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设置千分位,格式

    这三个使用和上面大同小异,不多说了

    round

    round表示四舍五入

    round(原数,取小数点后位数)。取得小数点后位数可以为负值,此时代表精确到整数位数

    select round(1234.567,1) from emp;
    
    rand()随机数

    随机获得一个0-1的小数

     select round(rand()*100,0) from emp;
    
    ifnull

    ifnull(原数据,替代值):当原数据为NULL时,用替代值替代原数据

    在数据库中,所有有null空值参与的数学运算,结果统统为空值

    所以为解决这个问题,我们可以用ifnull函数来处理nll

    select ename,sal+comm as salcomm from emp; 
    

    结果为:

    +--------+---------+
    | ename  | salcomm |
    +--------+---------+
    | SIMITH |    NULL |
    | ALLEN  | 1900.00 |
    | WARD   | 1750.00 |
    | JONES  |    NULL |
    | MARTIN | 2650.00 |
    | BLAKE  |    NULL |
    | CLARK  |    NULL |
    | SCOTT  |    NULL |
    | KING   |    NULL |
    | TURNER |    NULL |
    | ADAMS  |    NULL |
    | JAMES  |    NULL |
    | FORD   |    NULL |
    | MILLER |    NULL |
    +--------+---------+
    

    显然所有与NULL进行的运算结果都为NULL。下面我们用ifnull

    select ename,sal+ifnull(comm,0) as salcomm from emp; 
    
    +--------+---------+
    | ename  | salcomm |
    +--------+---------+
    | SIMITH |  800.00 |
    | ALLEN  | 1900.00 |
    | WARD   | 1750.00 |
    | JONES  | 2975.00 |
    | MARTIN | 2650.00 |
    | BLAKE  | 2850.00 |
    | CLARK  | 2450.00 |
    | SCOTT  | 3000.00 |
    | KING   | 5000.00 |
    | TURNER | 1500.00 |
    | ADAMS  | 1100.00 |
    | JAMES  |  950.00 |
    | FORD   | 3000.00 |
    | MILLER | 1300.00 |
    +--------+---------+
    
    case …when …then …when …then …else …end

    这函数虽然特殊,但也的确是单行处理函数

    示例:现在需要我们做个假账。不改变表中原有数据,只当显示时,将表中所有MANAGER工资上调10%。所有SALESMAN薪资上调50%。其他不变

    select 
    	ename,job,sal,
    	(case job when 'MANAGER' then sal*1.1 when 'SALESMAN' then sal*1.5 else sal end) as newsal
    from
    	emp;
    
    +--------+-----------+---------+---------+
    | ename  | job       | sal     | newsal  |
    +--------+-----------+---------+---------+
    | SIMITH | 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 |
    +--------+-----------+---------+---------+
    
    多行处理函数

    多行处理函数又名分组函数。默认整张表为一组

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

    以上这些函数都是同时对多行数据进行操作的。使用起来格式十分简单。

    值得注意的一点是:分组函数不会像单行处理函数一样对NULL需要依赖ifnull函数来处理NULL。分组函数是自动忽略NULL的。示例:

    select count(ename) from emp;
    
    +--------------+
    | count(ename) |
    +--------------+
    |           14 |
    +--------------+
    

    select count(comm) from emp;
    
    +-------------+
    | count(comm) |
    +-------------+
    |           3 |
    +-------------+
    

    原因很简单,comm中有很多NULL值在计数时被自动忽略掉了

    当然当我们需要把NULL值也进行计数时,可以:

    select count(ifnull(comm,0)) from emp;select count(*) from emp;
    

    特别注意:分组函数不能使用在where后。具体原因在分组查询时会讲解

    示例:

    select ename, sal from emp where sal>min(sal);
    
    ERROR 1111 (HY000): Invalid use of group function
    //错误的使用了分组函数
    

分组查询

分组查询主要有两个语句:

  • group by
  • having
group by

示例:按照工作岗位分组,然后对工资求均值

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

特别提示:select后只跟参与分组的字段以及分组函数。其他的一律不跟。没有意义并且可能会报错

示例2: 找出每个部门,不同岗位的最高薪资

可以将两个字段联合成一个字段来看

select
	deptno,job,max(sal)
from 
	emp
group by
	job,deptno;
+--------+-----------+----------+
| deptno | job       | max(sal) |
+--------+-----------+----------+
|     20 | CLERK     |  1100.00 |
|     30 | SALESMAN  |  1600.00 |
|     20 | MANAGER   |  2975.00 |
|     30 | MANAGER   |  2850.00 |
|     10 | MANAGER   |  2450.00 |
|     20 | ANALYST   |  3000.00 |
|     10 | PRESIDENT |  5000.00 |
|     30 | CLERK     |   950.00 |
|     10 | CLERK     |  1300.00 |
+--------+-----------+----------+

group by后面可以跟任意多字段。这个无所谓。但是一旦有group by,select后面跟的字段必须谨慎

having

示例:找出每个部门最高薪资,要求显示最高薪资大于等于3000的

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

除了使用where来执行,我们也可以使用having来执行

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

特别提示:having不能单独使用,必须和group by一起使用

而且having效率其实比较低,所以能用where尽量用where

示例2:找出每个部门平均薪资,要求显示平均薪资高于2000的。

此时,where确实就无能为力了。只能用having

select 
	deptno,avg(sal)
from 
	emp
group by
	deptno
having
	avg(sal)>2000;
+--------+-------------+
| deptno | avg(sal)    |
+--------+-------------+
|     20 | 2175.000000 |
|     10 | 2916.666667 |
+--------+-------------+

关键字书写顺序与执行顺序

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

特别提示:这就解释了为什么上面将分组函数放在where后会报错。因为where先于group by执行。而当执行到where后的分组函数时,系统实际上还没有进行分组,分组函数无法执行

再次重申一下:分组函数必须先分组再使用,哪怕默认的整表为一组也必须分组

示例:找出每个岗位的平均薪资,要求显示平均薪资大于1500的,除MANAGER之外按降序排列

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

特别提醒:SQL语句中,不等于的表示方法有很多,<>、!=、not in ()都可以表示不等于的含义

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值