13.1.简单查询一个字段?
select 字段名 from 表名
select from 都是关键字
字段名 表名是标识符
强调:
对于sql语句是通用的,
所有的sql语句都是以";"结尾
另外sql语句不区分大小写,都可以
13.2 查询DNAME这个字段
mysql> select dname from dept;
+------------+
| dname |
+------------+
| ACCOUNTING |
| RESEARCH |
| SALES |
| OPERATIONS |
+------------+
13.3查询多个字段怎么办?
查询的多字段用逗号隔开
mysql> select dname,loc from dept;
+------------+----------+
| dname | loc |
+------------+----------+
| ACCOUNTING | NEW YORK |
| RESEARCH | DALLAS |
| SALES | CHICAGO |
| OPERATIONS | BOSTON |
+------------+----------+
13.4查询所有字段,可以使用*,也可以把字段都写上
select * from dept
13.5给查询的列起别名
mysql> select deptno,dname as deptName from dept;
+--------+------------+
| deptno | deptName |
+--------+------------+
| 10 | ACCOUNTING |
| 20 | RESEARCH |
| 30 | SALES |
| 40 | OPERATIONS |
+--------+------------+
注意:select语句是不会修改原表的
as 关键字也可以省略, 使用空格
mysql> select deptno,dname deptName from dept;
13.5.1 若你起的别名存在空格怎么办? 例:你起的为 dept Name
可以加引号(''或"")将其包裹住
mysql> select dname 'dept Name' from dept;
+------------+
| dept Name |
+------------+
| ACCOUNTING |
| RESEARCH |
| SALES |
| OPERATIONS |
+------------+
注意:在所有的数据库中,字符串统一使用单引号括起来
单引号是标准,双引号在oracle中不能使用
14.计算每个员工的年薪
年薪:sal*12
mysql> select ename,sal*12 as salYear from emp; //字段可以使用数学表达式
+--------+----------+
| ename | salYear |
+--------+----------+
| SMITH | 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 |
+--------+----------+
15.条件查询
不是将所有的数据都查询出来,是查询出来符合条件的
语法格式:
select
字段一,字段二,...
from
表名
where
条件...
1.查询工资等于(=)800的员工姓名和编号
mysql> select empno,ename from emp where sal=800;
+-------+-------+
| empno | ename |
+-------+-------+
| 7369 | SMITH |
+-------+-------+
2.查询工资不等于(<>或!=)800的员工姓名和编号和薪资
mysql> select empno,ename,sal from emp where sal<>800;
+-------+--------+---------+
| empno | ename | sal |
+-------+--------+---------+
| 7499 | ALLEN | 1600.00 |
| 7521 | WARD | 1250.00 |
| 7566 | JONES | 2975.00 |
| 7654 | MARTIN | 1250.00 |
| 7698 | BLAKE | 2850.00 |
| 7782 | CLARK | 2450.00 |
| 7788 | SCOTT | 3000.00 |
| 7839 | KING | 5000.00 |
| 7844 | TURNER | 1500.00 |
| 7876 | ADAMS | 1100.00 |
| 7900 | JAMES | 950.00 |
| 7902 | FORD | 3000.00 |
| 7934 | MILLER | 1300.00 |
+-------+--------+---------+
3.查询薪资小于(<)2000的员工姓名和薪资
mysql> select ename,sal from emp where sal<2000;
+--------+---------+
| ename | sal |
+--------+---------+
| SMITH | 800.00 |
| ALLEN | 1600.00 |
| WARD | 1250.00 |
| MARTIN | 1250.00 |
| TURNER | 1500.00 |
| ADAMS | 1100.00 |
| JAMES | 950.00 |
| MILLER | 1300.00 |
4.查询SMITH得薪资和编号
mysql> select empno,sal from emp where ename='SMITH';
+-------+--------+
| empno | sal |
+-------+--------+
| 7369 | 800.00 |
+-------+--------+
5.查询薪资在2450到3000的员工的信息?闭区间between..and...或 >=...and <=...
select ename,sal from emp where sal between 2450 and 3000;
也可用
select ename,sal from emp where sal >= 2450 and sal <= 3000;
+-------+---------+
| ename | sal |
+-------+---------+
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| SCOTT | 3000.00 |
| FORD | 3000.00 |
+-------+---------+
注意:使用between and时必须遵顼左小右大的方式
6.查询哪些员工的津贴为null?
mysql> select ename,sal from emp where comm is null; //用is来表示等于,不能用=号来表示,因为数据库中的null表示什么也没有,不能用=来划等号
+--------+---------+------+
| ename | sal | comm |
+--------+---------+------+
| SMITH | 800.00 | NULL |
| JONES | 2975.00 | NULL |
| BLAKE | 2850.00 | NULL |
| CLARK | 2450.00 | NULL |
| SCOTT | 3000.00 | NULL |
| KING | 5000.00 | NULL |
| ADAMS | 1100.00 | NULL |
| JAMES | 950.00 | NULL |
| FORD | 3000.00 | NULL |
| MILLER | 1300.00 | NULL |
+--------+---------+------+
7.查询哪些员工的津贴不为null?(is not)
mysql> select ename,sal,comm from emp where comm is not null;
+--------+---------+---------+
| ename | sal | comm |
+--------+---------+---------+
| ALLEN | 1600.00 | 300.00 |
| WARD | 1250.00 | 500.00 |
| MARTIN | 1250.00 | 1400.00 |
| TURNER | 1500.00 | 0.00 |
+--------+---------+---------+
8.找出工作岗位是manager,并且工资大于2500的员工信息?
mysql> select ename,sal,job from emp where job='manager' and sal>2500;
+-------+---------+---------+
| ename | sal | job |
+-------+---------+---------+
| JONES | 2975.00 | MANAGER |
| BLAKE | 2850.00 | MANAGER |
+-------+---------+---------+
9.查询工作岗位是manager和salesman的员工信息?
mysql> select ename,job from emp where job='manager' or job='salesman';
+--------+----------+
| ename | job |
+--------+----------+
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| JONES | MANAGER |
| MARTIN | SALESMAN |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| TURNER | SALESMAN |
+--------+----------+
10.查询工资大于2500并且部门编号为10或者为20的员工信息?
mysql> select ename,sal,deptno from emp where sal>2500 and (deptno=10 or deptno=20); //加括号提升优先级
+-------+---------+--------+
| ename | sal | deptno |
+-------+---------+--------+
| JONES | 2975.00 | 20 |
| SCOTT | 3000.00 | 20 |
| KING | 5000.00 | 10 |
| FORD | 3000.00 | 20 |
+-------+---------+--------+
注意:and和or同时出现,and的优先级较高
11.查询工作岗位是manager和salesman的员工信息?(in)
mysql> select ename,job from emp where job in ('manager','salesman');
+--------+----------+
| ename | job |
+--------+----------+
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| JONES | MANAGER |
| MARTIN | SALESMAN |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| TURNER | SALESMAN |
+--------+----------+
注意:in不是一个区间,in后面跟的是具体的值.
12.查询工作岗位不是manager和salesman的员工信息?(not in)
mysql> select ename,job from emp where job not in ('manager','salesman');
+--------+-----------+
| ename | job |
+--------+-----------+
| SMITH | CLERK |
| SCOTT | ANALYST |
| KING | PRESIDENT |
| ADAMS | CLERK |
| JAMES | CLERK |
| FORD | ANALYST |
| MILLER | CLERK |
+--------+-----------+
12.找出名字中含有o的?(like模糊下查询)
% 百分号表示任意多个字符
_ 下划线表示任意一个字符
mysql> select ename from emp where ename like '%o%';
+-------+
| ename |
+-------+
| JONES |
| SCOTT |
| FORD |
+-------+
12.2找出第二个字母是a的员工?
mysql> select ename from emp where ename like '_a%';
+--------+
| ename |
+--------+
| WARD |
| MARTIN |
| JAMES |
+--------+
12.3找出第三个字母是r的?
mysql> select ename ename_R from emp where ename like '__r%';
+---------+
| ename_R |
+---------+
| WARD |
| MARTIN |
| TURNER |
| FORD |
+---------+
12.4例如现在有个表t_student学生表的name字段
有zhangsan,lisi,wangwu,jack_son,...
找出名字中含有"_"的?
1.select name from t_student where name like '%_%'; //这样不行,因为下划线_ 具有特殊意义,这样就会把所有的全部找出来
2.select name from t_sudent where name like '%\_%'; //需要用\进行转义
16.查询所有员工工资
1.查询工资并升序排列
mysql> select ename,sal from emp order by sal; //使用order by进行升序排列
+--------+---------+
| ename | sal |
+--------+---------+
| SMITH | 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 |
| FORD | 3000.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
+--------+---------+
2.查询工资并降序排列
mysql> select ename,sal from emp order by sal desc; //通过在最后加上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 |
| MARTIN | 1250.00 |
| WARD | 1250.00 |
| ADAMS | 1100.00 |
| JAMES | 950.00 |
| SMITH | 800.00 |
+--------+---------+
3.指定升序的话,使用asc
select ename,sal from emp order by sal asc;
4.查询员工的名字和薪资,先按照薪资的升序排列,若薪资相同则按照名字的升序排列?
mysql> select ename,sal from emp order by sal asc,ename asc; //sal 在前,起主导作用,只有在sal相等的时候,才会考虑ename的asc的排序.
+--------+---------+
| ename | sal |
+--------+---------+
| SMITH | 800.00 |
| JAMES | 950.00 |
| ADAMS | 1100.00 |
| MARTIN | 1250.00 |
| WARD | 1250.00 |
| MILLER | 1300.00 |
| TURNER | 1500.00 |
| ALLEN | 1600.00 |
| CLARK | 2450.00 |
| BLAKE | 2850.00 |
| JONES | 2975.00 |
| FORD | 3000.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
+--------+---------+
也可以这样写,
mysql> select ename,sal from emp order by 2,1;
//2就表示根据你写的字段的位置,2就是sal,1就是ename,但不建议这样写,因为字段的顺序很容易发生改变
+--------+---------+
| ename | sal |
+--------+---------+
| SMITH | 800.00 |
| JAMES | 950.00 |
| ADAMS | 1100.00 |
| MARTIN | 1250.00 |
| WARD | 1250.00 |
| MILLER | 1300.00 |
| TURNER | 1500.00 |
| ALLEN | 1600.00 |
| CLARK | 2450.00 |
| BLAKE | 2850.00 |
| JONES | 2975.00 |
| FORD | 3000.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
+--------+---------+
17.综合案例
1.找出工资在1250到3000的员工信息,要求按照薪资降序排列
mysql> select ename,sal from emp where sal between 1250 and 3000 order by sal desc;
+--------+---------+
| 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 |
+--------+---------+
注意:关键字顺序不能变
select
...
from
...
where
...
order by
....
以上语句的执行顺序必须掌握
第一步:from
第二部:where
第三步:select
第四步:排序(排序总是在最后的)
18.数据处理函数
数据处理函数又被称为单行处理函数
单行处理函数的特点:一个输入对呀一个输出
和单行处理函数对应的是:多行处理函数(多个输入对应一个输出)
18.1 常见的的单行处理函数有哪些?
lower 转换小写
mysql> select lower(ename) from emp;
+--------------+
| lower(ename) |
+--------------+
| smith |
| allen |
| ward |
| jones |
| martin |
| blake |
| clark |
| scott |
| king |
| turner |
| adams |
| james |
| ford |
| miller |
+--------------+
upper 转换大写
substr 取子串(substr(被截取的字符串,起始下标,截取的长度))
mysql> select substr(ename,1,3) from emp; //起始下标从一开始,没有0
+-------------------+
| substr(ename,1,3) |
+-------------------+
| SMI |
| ALL |
| WAR |
| JON |
| MAR |
| BLA |
| CLA |
| SCO |
| KIN |
| TUR |
| ADA |
| JAM |
| FOR |
| MIL |
+-------------------+
2.查询首字母为A的员工的名字(用substr函数)
mysql> select ename from emp where substr(ename,1,1)='A';
+-------+
| ename |
+-------+
| ALLEN |
| ADAMS |
+-------+
concat 字符串的拼接
1.将名字和薪资拼接到一块
mysql> select concat(ename,sal) from emp;
+-------------------+
| concat(ename,sal) |
+-------------------+
| SMITH800.00 |
| ALLEN1600.00 |
| WARD1250.00 |
| JONES2975.00 |
| MARTIN1250.00 |
| BLAKE2850.00 |
| CLARK2450.00 |
| SCOTT3000.00 |
| KING5000.00 |
| TURNER1500.00 |
| ADAMS1100.00 |
| JAMES950.00 |
| FORD3000.00 |
| MILLER1300.00 |
+-------------------+
2.将名字的首字母小写
mysql> select concat(lower(substr(ename,1,1)),substr(ename,2)) as result from emp;
+--------+
| result |
+--------+
| sMITH |
| aLLEN |
| wARD |
| jONES |
| mARTIN |
| bLAKE |
| cLARK |
| sCOTT |
| kING |
| tURNER |
| aDAMS |
| jAMES |
| fORD |
| mILLER |
+--------+
length 长度
获取名字的长度
mysql> select concat(length(ename),concat('-',ename)) as nameLength from emp;
+------------+
| nameLength |
+------------+
| 5-SMITH |
| 5-ALLEN |
| 4-WARD |
| 5-JONES |
| 6-MARTIN |
| 5-BLAKE |
| 5-CLARK |
| 5-SCOTT |
| 4-KING |
| 6-TURNER |
| 5-ADAMS |
| 5-JAMES |
| 4-FORD |
| 6-MILLER |
+------------+
trim 去空格
mysql> select * from emp where ename=trim(' SMITH'); //去除两端空格
+-------+-------+-------+------+------------+--------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+-------+------+------------+--------+------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
+-------+-------+-------+------+------------+--------+------+--------+
str_to_date 将字符串转换为日期
date_format 格式化日期
format 设置千分位
round 四舍五入
mysql> select round(123.5674,1) as result from emp;//第二位代表保留小数点后几位.如果是-1,则是保留到十位,向前推.
+--------+
| result |
+--------+
| 123.6 |
| 123.6 |
| 123.6 |
| 123.6 |
| 123.6 |
| 123.6 |
| 123.6 |
| 123.6 |
| 123.6 |
| 123.6 |
| 123.6 |
| 123.6 |
| 123.6 |
| 123.6 |
+--------+
rand() 生成随机数
mysql> select round(rand()*100,0) as result from emp; //生成0-100以内的随机整数
+--------+
| result |
+--------+
| 27 |
| 91 |
| 74 |
| 99 |
| 70 |
| 56 |
| 67 |
| 70 |
| 49 |
| 35 |
| 28 |
| 35 |
| 89 |
| 41 |
+--------+
ifnull 可以将null转换为一个具体值
计算每个员工的年薪
年薪 = (月薪+补助)*12
mysql> select ename,(sal+comm)*12 as yearsal from emp;
+--------+----------+
| ename | yearsal |
+--------+----------+
| SMITH | NULL |
| ALLEN | 22800.00 |
| WARD | 21000.00 |
| JONES | NULL |
| MARTIN | 31800.00 |
| BLAKE | NULL |
| CLARK | NULL |
| SCOTT | NULL |
| KING | NULL |
| TURNER | 18000.00 |
| ADAMS | NULL |
| JAMES | NULL |
| FORD | NULL |
| MILLER | NULL |
+--------+----------+
注意:null只要参与运算,最终结果一定是null,为了避免这个现象的出现,使用 ifnull函数
ifnull(数据,被当作那个值?) //如果数据为null时,将null当作哪个值
mysql> select ename,round((sal+ifnull(comm,0))*12,0) as yearsal from emp;
//如果comm为null则将其看为0对待运算
+--------+---------+
| ename | yearsal |
+--------+---------+
| SMITH | 9600 |
| ALLEN | 22800 |
| WARD | 21000 |
| JONES | 35700 |
| MARTIN | 31800 |
| BLAKE | 34200 |
| CLARK | 29400 |
| SCOTT | 36000 |
| KING | 60000 |
| TURNER | 18000 |
| ADAMS | 13200 |
| JAMES | 11400 |
| FORD | 36000 |
| MILLER | 15600 |
case..when..then..when..then..else..end
跟if else if else差不多
1.当员工的工作岗位是manager时,工资上调10%,当是salesman时,工资上调50%,其它正常
mysql> select ename,job,sal oldsal,(case job when 'manager' then sal*1.1 when 'salesman' then sal*1.5 else sal end) as newsal from emp;//打印出oldsal,和计算出newsal
+--------+-----------+---------+---------+
| 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 |
+--------+-----------+---------+---------+
1.什么是分组查询?
在实际应用中,可能有这样的需求,需要先进行分组,然后对每一组的数据进行操作,这个时候我们需要使用分组查询,怎么进行分组查询呢?
select
....
from
....
group by
....21.1将之前的关键字全部组合在一起,看他们的执行顺序?
select
...
where
...
group by
...
order by
...
以上关键字的顺序不能颠倒,需要记忆!!
执行顺序是什么?1.from
2.where
3.group by
4.select
5.order by
为什么分组函数不能直接使用在where后面?
select ename,sal from emp where sal>min(sal)?报错
因为分组函数使用的时候,必须先进行分组之后才能使用
where(第二个执行)执行的时候,还没有进行分组(第三个执行),所以where后面不能出现分组函数
21.2找出每个工作岗位的工资和?
mysql>
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|+-----------+----------+如果这样写:
select ename,job,sum(sal)
from emp
group by job;//这样没有意义,因为名字有14个,job有五个,不能进行整合注意:
在一条select语句当中,如果有group by语句的话,select后面只能跟: 参加分组的字段,以及分组函数,
其它一律不能跟
21.3找出每个部门的最高薪资?
mysql> select deptno,max(sal) from emp group by deptno;+--------+----------+| deptno |max(sal)|+--------+----------+|10|5000.00||20|3000.00||30|2850.00|+--------+----------+21.4找出每个部门,不同工作岗位的最高薪资?
两个分组条件,1.部门分组 2.工作岗位再进行分组,最后输出全部符合条件的
mysql>
select max(sal),job,deptno
from emp
group by deptno,job;//根据部门,然后再根据岗位进行分组,然后再找出最高工资进行输出.+----------+-----------+--------+|max(sal)| job | deptno |+----------+-----------+--------+|1300.00|CLERK|10||2450.00|MANAGER|10||5000.00|PRESIDENT|10||3000.00|ANALYST|20||1100.00|CLERK|20||2975.00|MANAGER|20||950.00|CLERK|30||2850.00|MANAGER|30||1600.00|SALESMAN|30|+----------+-----------+--------+21.5 找出每个部门的最高薪资,要求显示最高工资大于三千的?(使用having可以分完组后进行过滤),having不能单独使用,必须结合group by,并且having不能代替where
mysql> select max(sal),deptno from emp group by deptno having max(sal)>3000;+----------+--------+|max(sal)| deptno |+----------+--------+|5000.00|10|+----------+--------+第二种解法:
mysql> select max(sal),deptno from emp where sal>3000 group by deptno;//先用where进行过滤,把低于3000的过滤出去,然后再进行分组,也可以+----------+--------+|max(sal)| deptno |+----------+--------+|5000.00|10|+----------+--------+注意:where和having,能用where先用where.21.6找出每个人部门的平均工资,并且平均薪资高于2500的?
mysql> select avg(sal),deptno from emp group by deptno having avg(sal)>2500;//这个就只能用having了+-------------+--------+|avg(sal)| deptno |+-------------+--------+|2916.666667|10|+-------------+--------+
22.大总结(单表)
select
...
from
...
where
...
geoup by
...
having
...
order by
...
以上关键字只能按照上方的顺序来,不能颠倒
执行顺序为:1.from
2.where
3.group by
4.having
5.select
6.order by
从某张表中查询数
先经过where条件筛选出有价值的数据,
对这些数据再进行分组,
分组之后可以用having进行继续筛选
最后排序输出
22.1 找出每个岗位平均薪资,要求显示平均薪资大于1500的,除manager之外,要求平均薪资降序排列.
mysql> select avg(sal),job from emp where job !='manager' group by job having avg(sal)>1500 order by avg(sal) desc;//查询平均工资,和job,
条件是job不是manager的,分组为job,子条件为平均工资大于1500的,排序为平均工资降序.+-------------+-----------+|avg(sal)| job |+-------------+-----------+|5000.000000|PRESIDENT|//首席执行官岗位|3000.000000|ANALYST|//分析师+-------------+-----------+
23.去除重复记录
将查询结果去重,使用关键字distinct.不会对原表产生影响,只能出现所有字段的最前方.
mysql> select count(distinct(job)) as numDis from emp;
+--------+
| numDis |
+--------+
| 5 |
+--------+
24.连接查询(超级重点)
从一张表中单独查询,称为单表查询
emp和dept表联合起来查询数据,从emp标志取员工名字,从部门表中取部门名字
这种跨表查询,多张表联合起来查询数据,被称为连接查询.1.连接查询的分类?根据语法的年代分类:sql92:1992年出现的语法
sql99:1999年出现的语法
重点学习99.
表连接方式分类?内连接:
等值连接
非等值连接
自链接
外连接:左外连接(左连接)右外连接(右连接)
全连接
24.2当两张表进行连接查询时,没有任何条件的限制,会发生什么样的现象?
会发生笛卡尔积现象,没有任何限制时,查询的数量是两张表数量的乘积.1.怎么避免笛卡尔积现象?
连接时加条件,满足条件的记录筛选出来.24.2.1查询每个员工做所在部门的名称?
mysql> select ename,dname from emp,dept where emp.deptno = dept.deptno;//结果为14条结果+--------+------------+| ename | dname |+--------+------------+|CLARK|ACCOUNTING||KING|ACCOUNTING||MILLER|ACCOUNTING||SMITH|RESEARCH||JONES|RESEARCH||SCOTT|RESEARCH||ADAMS|RESEARCH||FORD|RESEARCH||ALLEN|SALES||WARD|SALES||MARTIN|SALES||BLAKE|SALES||TURNER|SALES||JAMES|SALES|+--------+------------+注意:匹配的结果少了,但匹配的次数不会减少.
并且效率不高,因为ename会去dept找,dname会区emp找.所以为了提高效率,可以将其查找的加上表名://给表起别名为e,d
mysql>select e.ename,d.dname from emp e,dept d where e.deptno = d.deptno;//sql92+--------+------------+| ename | dname |+--------+------------+|CLARK|ACCOUNTING||KING|ACCOUNTING||MILLER|ACCOUNTING||SMITH|RESEARCH||JONES|RESEARCH||SCOTT|RESEARCH||ADAMS|RESEARCH||FORD|RESEARCH||ALLEN|SALES||WARD|SALES||MARTIN|SALES||BLAKE|SALES||TURNER|SALES||JAMES|SALES|+--------+------------+
25内连接之等值连接
1.找出员工的部门,输出员工名字和部门名字
select
-> e.ename,d.dname
-> from
-> emp e
->(inner可省略) join
-> dept d
-> on
-> e.deptno=d.deptno; //等值连接,条件是等量关系
//join on sql99方法
sql92缺点:结构不清晰,将表的连接和后期进一步筛选的条件,都放到了where后面.
sql99的优点,表连接条件是独立的,连接之后,如果还需要进一步筛选,再往后添加where即可
+--------+------------+
| ename | dname |
+--------+------------+
| CLARK | ACCOUNTING |
| KING | ACCOUNTING |
| MILLER | ACCOUNTING |
| SMITH | RESEARCH |
| JONES | RESEARCH |
| SCOTT | RESEARCH |
| ADAMS | RESEARCH |
| FORD | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| MARTIN | SALES |
| BLAKE | SALES |
| TURNER | SALES |
| JAMES | SALES |
+--------+------------+
注意;sql99的语法
select
...
from
a
join
b
on
a和b的连接条件
where
筛选条件
26.内连接之非等值连接
1.找出每个员工的薪资等级,要求显示员工名 薪资 薪资等级?
mysql> select e.ename,e.sal,s.grade from emp e join
salgrade s
on
e.sal between s.losal and s.hisal;
+--------+---------+-------+
| ename | sal | grade |
+--------+---------+-------+
| SMITH | 800.00 | 1 |
| ALLEN | 1600.00 | 3 |
| WARD | 1250.00 | 2 |
| JONES | 2975.00 | 4 |
| MARTIN | 1250.00 | 2 |
| BLAKE | 2850.00 | 4 |
| CLARK | 2450.00 | 4 |
| SCOTT | 3000.00 | 4 |
| KING | 5000.00 | 5 |
| TURNER | 1500.00 | 3 |
| ADAMS | 1100.00 | 1 |
| JAMES | 950.00 | 1 |
| FORD | 3000.00 | 4 |
| MILLER | 1300.00 | 2 |
+--------+---------+-------+
27.内连接之自连接
查询员工的上级领导,要求显示员工名个对应的领导名?
mysql> select e.ename,e2.ename Pname from emp e
-> join emp e2
-> on
-> e.mgr = e2.empno; //员工的领导编号等于领导的员工编号
+--------+-------+
| ename | Pname |
+--------+-------+
| SMITH | FORD |
| ALLEN | BLAKE |
| WARD | BLAKE |
| JONES | KING |
| MARTIN | BLAKE |
| BLAKE | KING |
| CLARK | KING |
| SCOTT | JONES |
| TURNER | BLAKE |
| ADAMS | SCOTT |
| JAMES | BLAKE |
| FORD | JONES |
| MILLER | CLARK |
+--------+-------+
以上就是内连接的自连接,技巧:一张表看成两张表
28.外连接
1.找出员工所在部门,并且显示员工姓名和(全部)部门
mysql> select e.ename,d.dname from emp e
->right(outer可省略) join //右外连接,就是将join右边的为主表,left(左连接)反之.-> dept d
-> on
-> e.deptno = d.deptno;//right代表,将join关键字右边的这张表看成主表,主要是为了将这张表的数据全部查询出来,捎带着关练查询左边的表
而外连接的特点,是完成能够匹配上这个条件的数据查询出来.两张表或几张表没有主次关系
+--------+------------+| ename | dname |+--------+------------+|CLARK|ACCOUNTING||KING|ACCOUNTING||MILLER|ACCOUNTING||SMITH|RESEARCH||JONES|RESEARCH||SCOTT|RESEARCH||ADAMS|RESEARCH||FORD|RESEARCH||ALLEN|SALES||WARD|SALES||MARTIN|SALES||BLAKE|SALES||TURNER|SALES||JAMES|SALES||NULL|OPERATIONS|+--------+------------+注意:内连接与外连接的区别就是有没有right与left关键字,有就是外连接.
外连接的查询结果条数一定是>= 内连接的查询结果条数
mysql> select e.ename '员工名',e2.ename '领导名'
from emp as e
left join
emp e2
on
e.mgr =e2.empno;+--------+--------+| 员工名 | 领导名 |+--------+--------+|SMITH|FORD||ALLEN|BLAKE||WARD|BLAKE||JONES|KING||MARTIN|BLAKE||BLAKE|KING||CLARK|KING||SCOTT|JONES||KING|NULL||TURNER|BLAKE||ADAMS|SCOTT||JAMES|BLAKE||FORD|JONES||MILLER|CLARK|+--------+--------+
29.三张表,四张表的连接
语法:
select
...
from
a
join
b
on
a和b的连接条件
join
c
on
a和c的连接条件
join
d
on
a和d的连接条件
案例:(三张表进行连接)
找出每个员工的部门名称以及工资等级,要求显示员工名\部门名\薪资\薪资等级?
mysql> select e.ename,e.sal,d.dname,s.grade from emp as e
-> join dept as d
-> on
-> e.deptno = d.deptno
-> join salgrade as s
-> on
-> e.sal between s.losal and s.hisal;
+--------+---------+------------+-------+
| ename | sal | dname | grade |
+--------+---------+------------+-------+
| SMITH | 800.00 | RESEARCH | 1 |
| ALLEN | 1600.00 | SALES | 3 |
| WARD | 1250.00 | SALES | 2 |
| JONES | 2975.00 | RESEARCH | 4 |
| MARTIN | 1250.00 | SALES | 2 |
| BLAKE | 2850.00 | SALES | 4 |
| CLARK | 2450.00 | ACCOUNTING | 4 |
| SCOTT | 3000.00 | RESEARCH | 4 |
| KING | 5000.00 | ACCOUNTING | 5 |
| TURNER | 1500.00 | SALES | 3 |
| ADAMS | 1100.00 | RESEARCH | 1 |
| JAMES | 950.00 | SALES | 1 |
| FORD | 3000.00 | RESEARCH | 4 |
| MILLER | 1300.00 | ACCOUNTING | 2 |
+--------+---------+------------+-------+
2.案例:
找出每个员工的部门名称以及工资等级,还有上级领导,要求显示员工名\领导名\部门名\薪资\薪资等级?
select
e.ename,e2.ename Pname,e.sal,d.dname,s.grade
from emp e
left join emp e2
on
e.mgr = e2.empno
join dept d
on
e.deptno = d.deptno
join salgrade s
on
e.sal between s.losal and s.hisal;
+--------+-------+---------+------------+-------+
| ename | Pname | sal | dname | grade |
+--------+-------+---------+------------+-------+
| SMITH | FORD | 800.00 | RESEARCH | 1 |
| ALLEN | BLAKE | 1600.00 | SALES | 3 |
| WARD | BLAKE | 1250.00 | SALES | 2 |
| JONES | KING | 2975.00 | RESEARCH | 4 |
| MARTIN | BLAKE | 1250.00 | SALES | 2 |
| BLAKE | KING | 2850.00 | SALES | 4 |
| CLARK | KING | 2450.00 | ACCOUNTING | 4 |
| SCOTT | JONES | 3000.00 | RESEARCH | 4 |
| KING | NULL | 5000.00 | ACCOUNTING | 5 |
| TURNER | BLAKE | 1500.00 | SALES | 3 |
| ADAMS | SCOTT | 1100.00 | RESEARCH | 1 |
| JAMES | BLAKE | 950.00 | SALES | 1 |
| FORD | JONES | 3000.00 | RESEARCH | 4 |
| MILLER | CLARK | 1300.00 | ACCOUNTING | 2 |
+--------+-------+---------+------------+-------+
30.子查询?
30.1什么是子查询?
select语句中嵌套select语句,被嵌套的select语句被称为子查询.30.2子查询都可以出现在哪里呢?
select
..(select).
from
...(select)
where
..(select).30.3 where子句中出现子查询
案例:
找出比最低工资高的员工的姓名,薪资
mysql> select ename,sal from emp where sal>(select min(sal) from emp);//子查询先执行+--------+---------+| ename | sal |+--------+---------+|ALLEN|1600.00||WARD|1250.00||JONES|2975.00||MARTIN|1250.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|+--------+---------+30.4.from中的子查询,可以将子查询的查询结果当作一个临时表(技巧).案例:
找出每个岗位的平均工资的薪资等级.1.select avg(sal),job from emp group by job;
select
s.grade,t.*
from
salgrade s
join(select avg(sal)as avgSal,job from emp group by job)as t
on
avgSal between s.losal and s.hisal
order by
s.grade asc;+-------+-------------+-----------+| grade | avgSal | job |+-------+-------------+-----------+|1|1037.500000|CLERK||2|1400.000000|SALESMAN||4|3000.000000|ANALYST||4|2758.333333|MANAGER||5|5000.000000|PRESIDENT|+-------+-------------+-----------+30.5.select后面出现的子查询(这个内容不需要掌握,了解即可!!!)案例:
找出每个员工的部门名称,要求显示员工名,部门名?
mysql> select e.ename,d.dname from emp e
join dept d
on
e.deptno = d.deptno;+--------+------------+| ename | dname |+--------+------------+|CLARK|ACCOUNTING||KING|ACCOUNTING||MILLER|ACCOUNTING||SMITH|RESEARCH||JONES|RESEARCH||SCOTT|RESEARCH||ADAMS|RESEARCH||FORD|RESEARCH||ALLEN|SALES||WARD|SALES||MARTIN|SALES||BLAKE|SALES||TURNER|SALES||JAMES|SALES|+--------+------------+
第二种解决办法.select子查询
mysql>
select e.ename,(select d.dname,deptno from dept d where e.deptno=d.deptno) dname
from
emp e;//注意:对于select后面的子查询来说,这个子查询只能返回一个字段,+--------+------------+| ename | dname |+--------+------------+|SMITH|RESEARCH||ALLEN|SALES||WARD|SALES||JONES|RESEARCH||MARTIN|SALES||BLAKE|SALES||CLARK|ACCOUNTING||SCOTT|RESEARCH||KING|ACCOUNTING||TURNER|SALES||ADAMS|RESEARCH||JAMES|SALES||FORD|RESEARCH||MILLER|ACCOUNTING|+--------+------------+
31.union合并查询结果集
查询工作岗位是manager和salesman的员工?
mysql> select ename,job from emp where job='manager'
-> union
-> select ename,job from emp where job='salesman';
//使用union进行查询结果的合并,(union的效率的高一些),union把乘法变成了加法.
注意:union在进行结果集合并的时候,查询的结果列数得相同,在mysql中类型不一定一样,但在oracle中就会报错,oracle必须使其列数和类型都相同才能合并
+--------+----------+
| ename | job |
+--------+----------+
| JONES | MANAGER |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| MARTIN | SALESMAN |
| TURNER | SALESMAN |
+--------+----------+
32.limit(很重要)
limit的作用:将查询结果集的一部分取出来,通常使用在分页的查询当中.
limit的用法? [startIndex:起始下标],length:数量
1.按照薪资降序,取出排名在前五名的员工?
select ename,sal
from emp
order by sal desc
limit 0,5;
+-------+---------+
| ename | sal |
+-------+---------+
| KING | 5000.00 |
| SCOTT | 3000.00 |
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
注意:在mysql中limit是在order by之后执行
2.取出工资排名在3-5名的员工?
select ename,sal from emp
order by sal desc
limit 2,3; //3-5名,一共是3,4,5,三名,从三开始,也就是下标2,
+-------+---------+
| ename | sal |
+-------+---------+
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
3.去除工资排名在5-9名的数据?
select ename,sal from emp order by sal desc limit 4,5;
+--------+---------+
| ename | sal |
+--------+---------+
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| ALLEN | 1600.00 |
| TURNER | 1500.00 |
| MILLER | 1300.00 |
+--------+---------+
select
...
from
...
where
...
group by
...
having
...
order by
...
limit
...
执行顺序:
1.from
2.where
3.group by
4.having
5.select
6.order by
7.limit
34个作业题:
学号,姓名,年龄,性别邮箱地址
create table t_student(
no int,
name varchar(255),
age int(3),
gender char(1),
email varchar(255)
);
删除表:
drop table t_student; //当这张表不存在的时候会报错
drop table if exists t_student; //如果存在删除!
三.2 DML(数据操作语句)
1.4插入数据==(insert)(DML)==
insert into 表名(`字段`1,字段2,字段3) values(值1,值2,值3);
字段和值一一对应,数量要对应,数据类型也要对应.
insert into t_student(no,name,age,gender,email) values(1,'zhangqiankang',20,'m','2315119543@qq.com');
insert into t_student(email,no,name,age,gender) values('577934719@qq.com',2,'ymm',20,'f');
insert into t_student(no) values(3);
insert into t_student(name) values('ymmzqk')
注意:insert 只要执行成功了,就会增加一条记录,
没有给其它字段指定值的话,默认值是NULL.
删除表再创建.
drop tables if exists t_student;
create table t_student(
no int,
name varchar(32),
age int(3),
gender char(1) default 'm', //默认值
email varchar(255)
);
insert into t_student(no) values(1);
1.insert语句中的字段名可以省略嘛?
insert table t_student values(2); //报错
注意:前面的字段名省略的话,相当于都写上了,所以值也都要写上!
insert into t_student values(2,'lisi',20,'f','123456@qq.com'); //字段名都不写,所以相当于全都写上.
date是短日期,只包括年月日
datetime是长日期,包括年月日时分秒的娥信息
drop table if exists t_user;
create table t_user(
id int,
name varchar(32),
birth date,
create_time datetime
);注意:mysql 短日期默认格式:%Y-%m-%d.长日期格式:%Y-%m-%d %h:%i:%s
insert into t_user(id,name,birth,create_time)values(1,'lisi','2002-02-22','2022-03-22 22:16:45');
在mysql当中怎么获取当前时间呢?用now() 方法
insert into t_user(id,name,birth,create_time)values(2,'caobie','2001-05-12',now());
1.7改 update(DML)
update 表名 set 字段1=值1,字段2=值2 where 条件;
注意: 没有条件限制会导致所有数据全部更新.
update t_user set name= 'zhengtianyi',birth='2000-02-29',create_time = now() where id =1;
1.8 delete删除数据(DML)
delete from 表名 where 条件;
若无条件,则整张表都会被删除!!!
delete from t_user where id = 2;
四、34道作业题
1.取得每个部门最高薪水的人员名称
1.1select deptno,max(sal) as maxsal from emp group by deptno;
+--------+---------+
| deptno | maxsal |
+--------+---------+
| 10 | 5000.00 |
| 20 | 3000.00 |
| 30 | 2850.00 |
+--------+---------+
//取得每个部门最高的是多少.
1.2.select e.ename,t.* from emp e join (select deptno,max(sal) as maxsal from emp group by deptno) t
on e.deptno = t.deptno and e.sal = t.maxsal;
2.哪些人的薪水在部门的平均薪水之上?
2.1 select avg(sal) from emp group by deptno;
+-------------+
| avg(sal) |
+-------------+
| 2916.666667 |
| 2175.000000 |
| 1566.666667 |
+-------------+
2.2 select e.ename,e.sal from emp e join (select deptno,avg(sal) as avgsal from emp group by deptno) t on
e.deptno = t.deptno and e.sal>t.avgsal;
+-------+---------+
| ename | sal |
+-------+---------+
| ALLEN | 1600.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
| FORD | 3000.00 |
+-------+---------+
3.取得部门中(所有人的)平均的薪水等级
select grade,sal,deptno from emp join salgrade s on
sal between s.losal and s.hisal; //先找出每个人的薪资等级
+-------+---------+--------+
| GRADE | sal | deptno |
+-------+---------+--------+
| 1 | 800.00 | 20 |
| 3 | 1600.00 | 30 |
| 2 | 1250.00 | 30 |
| 4 | 2975.00 | 20 |
| 2 | 1250.00 | 30 |
| 4 | 2850.00 | 30 |
| 4 | 2450.00 | 10 |
| 4 | 3000.00 | 20 |
| 5 | 5000.00 | 10 |
| 3 | 1500.00 | 30 |
| 1 | 1100.00 | 20 |
| 1 | 950.00 | 30 |
| 4 | 3000.00 | 20 |
| 2 | 1300.00 | 10 |
+-------+---------+--------+
select avg(t.grade),deptno from (select grade,sal,deptno from emp join salgrade s on
sal between s.losal and s.hisal) t group by t.deptno;
//然后再根据部门求得薪资等级的平均值
+--------------+--------+
| avg(t.grade) | deptno |
+--------------+--------+
| 3.6667 | 10 |
| 2.8000 | 20 |
| 2.5000 | 30 |
+--------------+--------+
4、不准用组函数(Max),取得最高薪水(给出两种解决方案)
第一种:select sal from emp order by sal desc limit 1;//降序,取1.
+---------+
| sal |
+---------+
| 5000.00 |
+---------+
第二种:表连接
select sal from emp where sal not in (select distinct a.sal from emp a join emp b on
a.sal<b.sal
);//查询sal,并且条件是sal不在子查询内,而子查询是,令两个emp表(a,b)连接,并且条件为a的sal小于b的sal的 a的sal,并去重,所以只有最大的不会小于自己表中的sal.
5、取得平均薪水最高的部门的部门编号(至少给出两种解决方案)
select avg(sal) as avgsal,deptno from emp group by deptno;
select max(t.avgsal) Tsal,d.deptno from (select avg(sal) as avgsal,deptno from emp group by deptno) t join dept d on
d.deptno = t.deptno;
+-------------+--------+
| Tsal | deptno |
+-------------+--------+
| 2916.666667 | 10 |
+-------------+--------+
第二种:将查询出来部门的平均工资,进行降序排序,然后取出第一个就是最高的那个,然后跟部门表进行连接,取出和部门编号相同的即可
select avg(sal) as avgsal,deptno from emp group by deptno order by avgsal desc limit 1;
select t.avgsal Tsal_tow,d.deptno from (select avg(sal) as avgsal,deptno from emp group by deptno order by avgsal desc limit 1) t join dept d on
d.deptno = t.deptno;
+-------------+--------+
| Tsal_tow | deptno |
+-------------+--------+
| 2916.666667 | 10 |
+-------------+--------+
6.取得平均薪水最高的部门的部门名称
select avg(sal) avgsal_T from emp group by deptno order by avgsal_T desc limit 1;
select
d.dname
from
dept d
join
(select avg(sal) as avgsal,deptno from emp group by deptno order by avgsal desc limit 1) as t
on
d.deptno = t.deptno;
// 首先查询出来平均薪资最高的部门编号,然后再再进行表连接筛选出编号相同的部门名字。
+------------+
| dname |
+------------+
| ACCOUNTING |
+------------+
7.求平均薪水的等级最低的部门的部门名称
select avg(sal) avgsal,deptno from emp group by deptno order by avgsal asc limit 1; //先查出最低的平均工资编号
select
d.dname
from
dept d
join
(select avg(sal) as avgsal,deptno from emp group by deptno order by avgsal asc limit 1) as t
on
d.deptno = t.deptno;//然后再根据编号查出部门
+-------+
| dname |
+-------+
| SALES |
+-------+
8.取得比普通员工(员工代码没有在mgr字段上出现的)的最高薪水还要高的领导人姓名
1.员工代码没有在mgr上面也就是 not in,然后再取出这其中最高的工资为多少:
1.取出mgr不为null的.
select mgr from emp where mgr is not null;
select max(sal) from emp where empno not in (select mgr from emp where mgr is not null); //找出工人的最高薪资
select ename,sal from emp,(select max(sal) maxsal from emp where empno not in (select mgr from emp where mgr is not null)) t where sal>t.maxsal; //然后找出领导人姓名,条件是工资大于那个工人最高工资.
+-------+---------+
| ename | sal |
+-------+---------+
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
| FORD | 3000.00 |
+-------+---------+
9.取得薪水最高的前五名员工
select ename,sal from emp order by sal desc limit 0,5;+-------+---------+| ename | sal |+-------+---------+|KING|5000.00||SCOTT|3000.00||FORD|3000.00||JONES|2975.00||BLAKE|2850.00|+-------+---------+
10、取得薪水最高的第六到第十名员工
select ename,sal from emp order by sal desc limit 5,5;
+--------+---------+
| ename | sal |
+--------+---------+
| CLARK | 2450.00 |
| ALLEN | 1600.00 |
| TURNER | 1500.00 |
| MILLER | 1300.00 |
| MARTIN | 1250.00 |
+--------+---------+
//直接limit 5,5 从五开始,数量为5
11、取得最后入职的5名员工
select ename,hiredate,date_format(hiredate,'%Y%m%d') dateformathire from emp order by date_format(hiredate,'%Y%m%d') desc limit 5; //先将日期格式化,然后再将其排序降序输出,条数为5个
+--------+------------+--------------------------------+
| ename | hiredate | date_format(hiredate,'%Y%m%d') |
+--------+------------+--------------------------------+
| ADAMS | 1987-05-23 | 19870523 |
| SCOTT | 1987-04-19 | 19870419 |
| MILLER | 1982-01-23 | 19820123 |
| FORD | 1981-12-03 | 19811203 |
| JAMES | 1981-12-03 | 19811203 |
+--------+------------+--------------------------------+
12、取得每个薪水等级有多少员工
select s.grade,count(s.grade) Gradenum from emp e join salgrade s on
e.sal between s.losal and s.hisal group by s.grade;
+-------+----------+
| grade | Gradenum |
+-------+----------+
| 1 | 3 |
| 2 | 3 |
| 3 | 2 |
| 4 | 5 |
| 5 | 1 |
+-------+----------+
13.面试题(学生,课程,学生选课)
//课程表
+------+----------+----------+
| CNO | CNAME | CTEACHER |
+------+----------+----------+
| 1 | yuwen | zhang |
| 2 | zhengzhi | wang |
| 3 | yingyu | li |
| 4 | shuxue | zhao |
| 5 | wuli | liming |
+------+----------+----------+
//学生表
+------+----------+
| SNO | SNAME |
+------+----------+
| 1 | student1 |
| 2 | student2 |
| 3 | student3 |
| 4 | student4 |
+------+----------+
//学生选课表
+------+------+---------+
| SNO | CNO | SCGRADE |
+------+------+---------+
| 2 | 1 | 60 |
| 2 | 3 | 60 |
| 2 | 4 | 60 |
| 2 | 5 | 40 |
| 3 | 3 | 80 |
| 1 | 1 | 40 |
| 1 | 2 | 30 |
| 1 | 4 | 80 |
| 1 | 5 | 60 |
+------+------+---------+
1.找出没选过“黎明”老师的所有学生姓名
select distinct sname from s where
sno not in (select sno from sc where cno=(select cno from c where cteacher='liming'));
+----------+
| sname |
+----------+
| student3 |
| student4 |
+----------+
/先通过liming找出对应的课程号,然后通过课程号找出选这个课程号的学号,然后再输出不是这些学号的学生姓名
2.列出 2 门以上(含 2 门)不及格学生姓名及平均成绩。
select count(scgrade) as rejgradenum,sno from sc where scgrade<60 group by SNO having rejgradenum>=2;
//先找出不及格两门以上的学生的学号
select sname,avg(sc.scgrade) from s join (select count(scgrade) as rejgradenum,sno from sc where scgrade<60 group by SNO having rejgradenum>=2) t
on
t.sno =s.sno
join sc
on
sc.sno = t.sno;
//然后再查询学生的姓名,及他全部的成绩的平均成绩,所以t临时表和s可以查到学生姓名,再连接sc表可以将这个学生的全部成绩求平均.
+----------+-----------------+
| sname | avg(sc.scgrade) |
+----------+-----------------+
| student1 | 52.5 |
+----------+-----------------+
3.即学过 1 号课程又学过 2 号课所有学生的姓名。
select sno from sc where cno='1' ;
select sno from sc where cno='2' ;
//先查询出等于课程号等于1的学号,
//再查询出课程号等于2的学生的学号
select s.sname from s join (select sno from sc where cno='1') a
on
s.sno = a.sno
join(select sno from sc where cno='2') b on a.sno=b.sno;
//查询课程号为1的学号和课程号为2的学号进行相等,抽取出学号,然后确定出选择一又选择二的学号,然后用确定的学号对s学生表进行匹配姓名,然后输出
14.列出所有员工及领导的姓名
select e.ename,ifnull(m.ename,'没有上级') from emp e left join emp m
on
e.mgr = m.empno;
//两张emp员工表进行连接,条件是e的mgr属性值等于m.empno属性值
+--------+----------------------------+
| ename | ifnull(m.ename,'没有上级') |
+--------+----------------------------+
| SMITH | FORD |
| ALLEN | BLAKE |
| WARD | BLAKE |
| JONES | KING |
| MARTIN | BLAKE |
| BLAKE | KING |
| CLARK | KING |
| SCOTT | JONES |
| KING | 没有上级 |
| TURNER | BLAKE |
| ADAMS | SCOTT |
| JAMES | BLAKE |
| FORD | JONES |
| MILLER | CLARK |
+--------+----------------------------+
15、列出受雇日期早于其直接上级的所有员工的编号,姓名,部门名称
select mgr from emp;
select t.empno,t.deptno,t.ename
from
emp e
join
(select empno ,deptno,ename,mgr,date_format(t1.hiredate,'%Y%m%d') as tdate from emp t1) t
on
e.empno = t.mgr and t.tdate<date_format(e.hiredate,'%Y%m%d');
//先查询出来比上级早的员工姓名部门编号
+-------+--------+-------+
| empno | deptno | ename |
+-------+--------+-------+
| 7369 | 20 | SMITH |
| 7499 | 30 | ALLEN |
| 7521 | 30 | WARD |
| 7566 | 20 | JONES |
| 7698 | 30 | BLAKE |
| 7782 | 10 | CLARK |
+-------+--------+-------+
select
m.empno,m.ename,d.dname
from
dept d
join
(
select
t.empno,t.deptno,t.ename
from
emp e
join
(select
empno ,deptno,ename,mgr,date_format(t1.hiredate,'%Y%m%d') as tdate
from
emp t1) t
on
e.empno = t.mgr and t.tdate<date_format(e.hiredate,'%Y%m%d')) m
on
m.deptno = d.deptno
order by
empno asc;
+-------+-------+------------+
| empno | ename | dname |
+-------+-------+------------+
| 7369 | SMITH | RESEARCH |
| 7499 | ALLEN | SALES |
| 7521 | WARD | SALES |
| 7566 | JONES | RESEARCH |
| 7698 | BLAKE | SALES |
| 7782 | CLARK | ACCOUNTING |
+-------+-------+------------+
select deptno,count(*) num from emp group by deptno having num>=5;
//
select d.dname,t.num from dept d join (select deptno,count(*) num from emp group by deptno having num>=5) t on
d.deptno = t.deptno;
+----------+-----+
| dname | num |
+----------+-----+
| RESEARCH | 5 |
| SALES | 6 |
+----------+-----+
select e.ename,e.empno,e.deptno from emp e where job='clerk';
//先查出工作是clerk的姓名编号的部门编号
select t.ename,d.dname,m.num from dept d join (select e.ename,e.empno,e.deptno from emp e where job='clerk') t on
t.deptno = d.deptno
//然后连接部门表查出部门名称,条件是部门编号等于部门编号
join (select deptno,count(deptno) as num from emp group by deptno) m
on
m.deptno = t.deptno;
//然后再查出这个部门的人数,通过部门编号
+--------+------------+-----+
| ename | dname | num |
+--------+------------+-----+
| SMITH | RESEARCH | 5 |
| ADAMS | RESEARCH | 5 |
| JAMES | SALES | 6 |
| MILLER | ACCOUNTING | 3 |
+--------+------------+-----+
20、列出最低薪金大于 1500 的各种工作及从事此工作的全部雇员人数.
select e.job from emp e group by job having min(sal)>1500;
//先查出最低薪资大于1500的工作是什么
select e2.job,count(e2.job) from emp e2 join (select e.job from emp e group by job having min(sal)>1500) t on
t.job = e2.job
group by job;
//然后再查出这个工作有多少人,通过表连接,然后通过工作分组分组
+-----------+---------------+
| job | count(e2.job) |
+-----------+---------------+
| ANALYST | 2 |
| MANAGER | 3 |
| PRESIDENT | 1 |
+-----------+---------------+
21.列出在部门"SALES"<销售部>工作的员工的姓名,假定不知道销售部的部 门编号.
1.select ename,job from emp where deptno not in (10,20,40);
+--------+----------+
| ename | job |
+--------+----------+
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| MARTIN | SALESMAN |
| BLAKE | MANAGER |
| TURNER | SALESMAN |
| JAMES | CLERK |
+--------+----------+
22.列出薪金高于公司平均薪金的所有员工,所在部门,上级领导,雇员的工资等 级.
select avg(sal) as avgsal from emp;
//先查询出公司的平均工资avgsal
select e.ename,e.sal,d.dname,e2.ename,s.grade from emp e join (select avg(sal) as avgsal from emp) t
on
e.sal > t.avgsal
join dept d
on
d.deptno = e.deptno
left join emp e2
on
e.mgr = e2.empno
join salgrade s
on
e.sal between s.losal and s.hisal;
//然后再跟emp连接,查出大于avgsal的名字,工资,等,
再跟部门表连接。查出部门名称,
再跟emp连接一下,然后设置左为主表,查出前面的符合要求的员工的上级领导的编号。
再与工资表连接,查出前面工资的等级,结束
+-------+---------+------------+-------+-------+
| ename | sal | dname | ename | grade |
+-------+---------+------------+-------+-------+
| JONES | 2975.00 | RESEARCH | KING | 4 |
| BLAKE | 2850.00 | SALES | KING | 4 |
| CLARK | 2450.00 | ACCOUNTING | KING | 4 |
| SCOTT | 3000.00 | RESEARCH | JONES | 4 |
| KING | 5000.00 | ACCOUNTING | NULL | 5 |
| FORD | 3000.00 | RESEARCH | JONES | 4 |
+-------+---------+------------+-------+-------+
23.列出与"SCOTT"从事相同工作的所有员工及部门名称.
select e.job from emp e where ename='scott';//先进行job的查找,条件是name等于scott
select e2.ename,e2.deptno,d.dname from emp e2 join(select e.job from emp e where ename='scott') t
on
e2.job = t.job
join dept d
on
d.deptno = e2.deptno
where e2.ename <>'scott';//然后再进行查找job的scott这个员工的job的,并且name不是scott的,然后再连接部门表,进行查找部门名称.+-------+--------+----------+| ename | deptno | dname |+-------+--------+----------+|FORD|20|RESEARCH|+-------+--------+----------+
24、列出薪金等于部门 30 中员工的薪金的其他员工的姓名和薪金.
select e2.sal,e2.ename from emp e2 join(select e.sal from emp e where deptno=30) s on e2.sal=s.sal where deptno!=30;//先查找部门等于三十的员工薪资 t,
然后在进行表的连接,查找薪资等于t的员工信息,并且条件是部门不等于30
结果为空!---------------------------------------------------
25、列出薪金高于在部门 30 工作的所有员工的薪金的员工姓名和薪金.部门名 称.
select distinct e2.sal,e2.ename,d.dname from emp e2 join (select max(e.sal) sal from emp e where deptno=30) s on e2.sal>s.sal
join dept d on e2.deptno=d.deptno
where e2.deptno!=30 ;
//大于,所以是>,并且连接部门,然后连接部门表查询部门名称
+---------+-------+------------+
| sal | ename | dname |
+---------+-------+------------+
| 2975.00 | JONES | RESEARCH |
| 3000.00 | SCOTT | RESEARCH |
| 5000.00 | KING | ACCOUNTING |
| 3000.00 | FORD | RESEARCH |
+---------+-------+------------+
26、列出在每个部门工作的员工数量,平均工资和平均服务期限.
select count(*) num,avg(sal) as avgsal,ceil(avg(date_format(now(),'%Y')-date_format(hiredate,'%Y'))) avgyear from emp group by deptno;
//查询数量 平均工资 平均服务年限,通过ceil方法进行向上取整
+-----+-------------+---------+
| num | avgsal | avgyear |
+-----+-------------+---------+
| 3 | 2916.666667 | 41 |
| 5 | 2175.000000 | 39 |
| 6 | 1566.666667 | 41 |
+-----+-------------+---------+
27、列出所有员工的姓名、部门名称和工资
select e.ename,d.dname,sal from emp e join
dept d
on
e.deptno= d.deptno;
//两个表的连接,比较简单
+--------+------------+---------+
| ename | dname | sal |
+--------+------------+---------+
| CLARK | ACCOUNTING | 2450.00 |
| KING | ACCOUNTING | 5000.00 |
| MILLER | ACCOUNTING | 1300.00 |
| SMITH | RESEARCH | 800.00 |
| JONES | RESEARCH | 2975.00 |
| SCOTT | RESEARCH | 3000.00 |
| ADAMS | RESEARCH | 1100.00 |
| FORD | RESEARCH | 3000.00 |
| ALLEN | SALES | 1600.00 |
| WARD | SALES | 1250.00 |
| MARTIN | SALES | 1250.00 |
| BLAKE | SALES | 2850.00 |
| TURNER | SALES | 1500.00 |
| JAMES | SALES | 950.00 |
+--------+------------+---------+
28.列出所有部门的详细信息和人数
select d.*,count(e.deptno) '人数' from dept d left join emp e
on
e.deptno = d.deptno
group by e.deptno;
//这里选择左边的表为主表,因为40编号的部门没有人员,若不为主表则匹配deptno不成功,则会被筛掉,所以设为主表.
//2.然后查人数时,要以e.deptno来查,因为e.deptno在40编号的部门为0,才能输出正确.
//若以d.deptno来查count时,40部门会查出1,主表的40部门没有匹配也会被当作一个成功的值
+--------+------------+----------+------+
| DEPTNO | DNAME | LOC | 人数 |
+--------+------------+----------+------+
| 40 | OPERATIONS | BOSTON | 0 |
| 10 | ACCOUNTING | NEW YORK | 3 |
| 20 | RESEARCH | DALLAS | 5 |
| 30 | SALES | CHICAGO | 6 |
+--------+------------+----------+------+
29.列出各种工作的最低工资及从事此工作的雇员姓名
select e.job,min(sal) minsal from emp e group by job;
//先查找出工作和最低工资是多少
select t.* from emp t join (select e.job,min(sal) minsal from emp e group by job) m
on
m.job = t.job and m.minsal =t.sal;
//然后再进行表连接,查找所有.t表与m临时表进行连接,条件是工作相匹配并且工资相匹配
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 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 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
+-------+--------+-----------+------+------------+---------+---------+--------+
30、列出各个部门的 MANAGER(领导)的最低薪金
select
e.deptno,min(e.sal)
from
emp e
where
e.job ='manager'
group by
deptno;
//通过emp表的查询,然后条件是工作是manager的,并且再通过deptno部门编号分组,就可以查到部门的最低manager的薪资了.
+--------+------------+
| deptno | min(e.sal) |
+--------+------------+
| 10 | 2450.00 |
| 20 | 2975.00 |
| 30 | 2850.00 |
+--------+------------+
31、列出所有员工的年工资,按年薪从低到高排序
select
ename,(sal*12+ifnull(comm,0)) yearsal
from
emp
order by
yearsal asc;
//年薪,通过sal*12加上comm补助,若为空,则设置为0
+--------+----------+
| ename | yearsal |
+--------+----------+
| SMITH | 9600.00 |
| JAMES | 11400.00 |
| ADAMS | 13200.00 |
| WARD | 15500.00 |
| MILLER | 15600.00 |
| MARTIN | 16400.00 |
| TURNER | 18000.00 |
| ALLEN | 19500.00 |
| CLARK | 29400.00 |
| BLAKE | 34200.00 |
| JONES | 35700.00 |
| FORD | 36000.00 |
| SCOTT | 36000.00 |
| KING | 60000.00 |
+--------+----------+
32、求出员工领导的薪水超过 3000 的员工名称与领导名称
select
e.ename,e.mgr
from emp;
//先查询emp中mgr与name
select
t.ename,m.ename
from emp t
join
(select e.ename,e.mgr from emp e) m
on
m.mgr = t.empno
where
t.sal>3000;
//再通过表连接,进行查询,条件是mgr等于empno,则输出这个empno的name
+-------+-------+
| ename | ename |
+-------+-------+
| KING | JONES |
| KING | BLAKE |
| KING | CLARK |
+-------+-------+
33、求出部门名称中,带’S’字符的部门员工的工资合计、部门人数.
select d.deptno,d.dname from dept d where d.dname like '%s%';
//首先查出带s的部门,为3个
+--------+------------+
| deptno | dname |
+--------+------------+
| 20 | RESEARCH |
| 30 | SALES |
| 40 | OPERATIONS |
+--------+------------+
select t.dname,sum(e.sal),count(e.deptno) from emp e right join (select d.deptno,d.dname from dept d where d.dname like '%s%') t
on
e.deptno = t.deptno
group by t.deptno;
//然后再通过表的连接,进行查询工资的合计和人数,条件为部门编号等于部门编号,通过部门编号分组
+------------+------------+-----------------+
| dname | sum(e.sal) | count(e.deptno) |
+------------+------------+-----------------+
| RESEARCH | 10875.00 | 5 |
| SALES | 9400.00 | 6 |
| OPERATIONS | NULL | 0 |
+------------+------------+-----------------+
drop table if exists t_student;
drop table if exists t_class;
create table t_class(
cno int primary key ,
classname varchar(255));
create table t_student(
no int primary key auto_increment,
name varchar(255),
cno int ,
foreign key(cno) references t_class(cno));//外键是cno,然后参考或继承于t_class表中的cno
insert into t_class(cno,classname)values(100,'高三一班');
insert into t_class(cno,classname)values(101,'高三二班');
insert into t_student(name,calssno)values('jack','100');
insert into t_student(no,name,cno)values('lisi','100');
insert into t_student(no,name,cno)values('zhangsan','101');
insert into t_student(no,name,cno)values('wangliu','101');
insert into t_student(no,name,cno)values('beixi','101');
select * from t_class;
select * from t_student;
思考?子表中的外键引用父表中的某个字段,被引用的这个字段必须是主键嘛?
被引用的不一定是主键,但一定是唯一的,unique约束.测试:外键(子表)可以为空嘛?
可以为null,
9.1什么是索引?
索引是数据库表的字段上添加的,是为了提高查询效率存在一种机制.
一张表的一个字段可以添加一个索引,当前,多个字段联合起来也可以添加索引.
索引相当于目录,为了缩小扫描范围而存在的一种机制.
比如对于字典来说,一页一页挨着找,任务量非常的大,如果通过目录进行锁定在一个范围,那么查找起来会非常快的.效率很高
select * from t_user where name='jack';
这条sql语句会去name字段上扫描.因为查询条件是name='jack'
如果name字段上"没有"添加索引,那么将会全扫描.将name上的值全一一对比,效率很低.
msyql的查询方式有两种方式:
全表扫描
根据索引检索.
注意:目录也需要排序,才会有区间,才会有区间查找.这样方便查找,效率更高.
在mysql数据库当中索引也是需要排序的(a.b.c.d...).并且这个索引的排序和TreeSet(TreeMap)数据结构相同,TreeSet底层是一个自平衡的二叉树.
mysql中的索引是一个B-Tree数据结构.遵循左小右大原则存放,采用中序遍历方式遍历取数据.
9.1索引的实现原理
现在有这么一张表
t_user
id(PK) name (物理地址)
----------------------------
100 zqk 0x123
101 jack 0x124
120 tom 0x125
130 lisi 0x126
99 wangwu 0x127
88 zhaoliu 0x128
55 beixi 0x129
sql查询语句:
select * from t_user where id=101
通过id为101这个条件查找,又因为主键自动设置索引,并且存储起来,所以在查找101时就是通过索引查找,更加高效,其内部使用了B-Tree二分查找.
提示:在mysql中,索引是一个单独的对象,不同的存储引擎以不同的形式存在,在MyISAM中,索引存储在.MYI文件中,在InnoDB中,索引存储在一个逻辑名称为tablespace当中,在MEMORY引擎当中,索引在内存当中,索引在mysql当中都是以一个树的形式存在的.(自平衡二叉树:B-Tree)
画图演示如下:
9.1.2 主键上,unique字段上都会自动添加索引的.
什么条件下,会考虑给字段添加索引呢?
1.数据量庞大(测试!)
2.某个字段经常出现在where后面,以条件的形式存在,总是被扫描.
3.该字段很少使用DML语句(delete,update,insert)操作.
因为DML后,索引需要重新排序.
建议不要随便添加索引,因为索引也是需要维护的.太多的索引反而减低系统的性能.
建议通过主键查询 unique约束的字段进行查询,效率反而是比较高的.
9.2索引的创建和删除
创建:
create index emp_ename_index on emp(ename);
给emp的ename创建索引,起名为emp_ename_index
删除索引:
drop index emp_ename_index on emp;
将emp表上的emp_ename_index索引删除.
怎么查看一个sql语句是否使用了索引?(explain关键字)
explain select * from emp where ename='king'+----+-------------+-------+------+---------------+------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+|1|SIMPLE| emp |ALL|NULL|NULL|NULL|NULL|14| Using where |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+//可以发现,类型为all,全扫描,搜索了14行,没有索引.9.2.2我们手动给它加上索引之后,在进行查询
create index emp_ename_index on emp(ename);
explain select * from emp where ename='king';+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+|1|SIMPLE| emp | ref | emp_ename_index | emp_ename_index |33|const|1| Using where |+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+//可以看到它只搜索了一条就查询出来了..
9.3索引的失效
1.模糊查询%开始.
explain select * from emp where ename like '%t';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+ //14条匹配次数
ename即使添加了索引,也不会走索引,因为%开始,不确定前面的数据,所以每一项数据都得查找.
::尽量避免模糊查询以"%"开始.
2.使用or得时候会失效.
如果使用or那么要求or两边得条件都要有索引,才会走索引,如果其中一边没有没有索引,那么另一个字段的索引不会实现,所以在开发中不建议使用or得原因.
可以使用union连接结果进行查询!!
3.使用复合索引的时候,没有使用左侧列查找,索引失效!
3.1什么是复合索引?
两个字段,或者更多的字段联合起来添加一个索引,叫做复合索引.
create index emp_job_sal_index on emp(job,sal);
explain select * from emp where job='manager';+----+-------------+-------+------+-------------------+-------------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-------------------+-------------------+---------+-------+------+-------------+
| 1 | SIMPLE | emp | ref | emp_job_sal_index | emp_job_sal_index | 30 | const | 3 | Using where |
+----+-------------+-------+------+-------------------+-------------------+---------+-------+------+-------------+
explain select * from emp where sal=800; //查询时使用了左侧没有使用右侧,索引成功
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+//查询中使用右侧,没有使用左侧的job,索引失效.
最左原则!!!
4.在where当中索引列(这个字段)参加了数学运算,索引失效!
create index emp_sal on emp(sal);
explain select * from emp where sal+1 >800;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
//索引失效,查询次数为全表.
5.在where当中索引使用了单行函数
create index emp_ename on emp(ename);
explain select * from emp where lower(ename)='smith';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+//索引失效,查询次数为全部.
10.1什么是视图?
view:站在不同的角度去看待同一份数据.
10.2怎么创建视图对象? 怎么删除视图对象?
create view emp_view as select * from emp;//视图对应的后面只能是DQL语句
复制一张表:
create table dept2 as select * from dept;
create view dept2_view as select * from dept2;
10.3删除视图:
drop view dept2_view;
注意:只有DQL语句才能以view的形式创建.(select)
10.4我们用视图做什么?
对视图进行增删改查,会影响到原表数据.
10.5视图对象在实际开发中到底有什么用?
简化sql语句.视图可以进行简化sql语句来创建一个视图表示,既可以进行增删改查,又可以达到简化的目的.
例:
create view
emp_dept_view
as
select
e.ename,e.sal,d.dname
from
emp e
join
dept d
on
d.deptno = e.deptno;
//这样,一个emp_dept_view视图就代替了下面的sql语句,如果一条sql语句非常复杂(一条一张A4纸),那么视图是非常简化sql语句的!!
当你需要修改的时候,只需要修改视图所映射的SQL语句!
视图也是存储在硬盘上的,不会消失。
优点:
方便,简化开发,利于维护