mysql--DQL 迈不过友情╰ 2022-10-23 08:28 148阅读 0赞 1. 简单地查询语句(DQL) 语法格式: select 字段名1, 字段名2… from 表名; 提示: 1. 任何一条sql语句以分号(;)结尾. 2. sql语句不区分大小写. mysql> select ENAME, empno FROM emp; ±-------±------+ | ENAME | empno | ±-------±------+ | SMITH | 7369 | | ALLEN | 7499 | | WARD | 7521 | | JONES | 7566 | | MARTIN | 7654 | | BLAKE | 7698 | | CLARK | 7782 | | SCOTT | 7788 | | KING | 7839 | | TURNER | 7844 | | ADAMS | 7876 | | JAMES | 7900 | | FORD | 7902 | | MILLER | 7934 | ±-------±------+ mysql> select \-> empno, ename \-> from \-> emp; (这么写可以区分开关键字) 查看员工年薪? emp表中只有月薪.(字段可以参与数学运算) mysql> select ename, sal \* 12 from emp; ±-------±---------+ | ename | sal \* 12 | ±-------±---------+ | 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 | ±-------±---------+ 给查询结果的列重命名? mysql> select ename, sal \* 12 as yearsal from emp; ±-------±---------+ | ename | yearsal | ±-------±---------+ | 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 | ±-------±---------+ as关键字可以省略. mysql> select ename, sal \* 12 yearsal from emp; ±-------±---------+ | ename | yearsal | ±-------±---------+ | 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 | ±-------±---------+ 别名中有中文? select ename, sal \* 12 as 年薪 from emp;//错误 select ename, sal \* 12 as ‘年薪’ from emp; mysql> select ename, sal \* 12 as ‘年薪’ from emp; ±-------±---------+ | ename | 年薪 | ±-------±---------+ | 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 | ±-------±---------+ 注意:标准sql语句中要求字符串使用单引号括起来.虽然mysql支持双引号,尽量别用, 兼容性降低. 查询所有字段? mysql> select \* from emp; (效率很低,实际开发中尽量别用) ±------±-------±----------±-----±-----------±--------±--------±-------+ | EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO | ±------±-------±----------±-----±-----------±--------±--------±-------+ | 7369 | SMITH | 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 | 0.00 | 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 | ±------±-------±----------±-----±-----------±--------±--------±-------+ 2. 条件查询 语法格式: select 字段1, 字段2… from 表名 where 条件; 执行顺序: 先from, 然后where, 最后select 查询工资等于5000的员工姓名? mysql> select ename from emp where sal = 5000; ±------+ | ename | ±------+ | KING | ±------+ 查询SMITH的工资? mysql> select sal from emp where ename = ‘SMITH’; ±-------+ | sal | ±-------+ | 800.00 | ±-------+ 找出工资大于等于3000 的员工? mysql> select ename, sal from emp where sal >= 3000; ±------±--------+ | ename | sal | ±------±--------+ | SCOTT | 3000.00 | | KING | 5000.00 | | FORD | 3000.00 | ±------±--------+ 找出工资不等于3000的? select ename, sal from emp where sal <> 3000; 或 select ename, sal from emp where sal != 3000; 找出工资在1100和3000之间的员工,包括1100和3000? select ename, sal from emp where sal >= 1100 and sal <= 3000; 或 select ename, sal from emp where sal between 1100 and 3000;(闭区间) 注意:between and用在数值查询时必须左小右大. between and除了可以使用在数字方面之外, 还可以使用在字符串方面. mysql> select ename from emp where ename between ‘A’ and ‘C’; ±------+ | ename | ±------+ | ALLEN | | BLAKE | | ADAMS | ±------+ between and在查询字符串的时候是左闭右开,上面的例子,和C相匹配的字符串不作为查询结果. 找出那些人津贴为空? 在数据库中NULL不是一个值,代表什么也没有,为空. 空不是一个值,不能用等号衡量. 必须使用is null或者 is not null mysql> select ename, sal, comm from emp where comm 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 | ±-------±--------±-----+ 找出那些人没有津贴?(0.00或者NULL) mysql> select ename, sal, comm from emp where comm is null or sal = 0; 找出工作岗位是MANAGER和SALESMAN的员工? select ename, job from emp where job = ‘MANAGER’ or job = ‘SALSMAN’; and和or联合使用:找出薪资大于1000的并且部门编号是20或30的员工? select ename, sal, deptno from emp where sal > 1000 and deptno = 20 or deptno = 30; //这么写不对,因为and优先级比or要高, sal > 1000 和deptno = 20 会组成一个条件组,deptno = 30会组成另外一个条件组. select ename, sal, deptno from emp where sal > 1000 and (dept = 20 or dept = 30); 注意:当运算符的优先级不确定的时候,用小括号来自定义优先级. in等同于or:找出工作岗位是MANAGER和SALSMAN的员工? select ename, job, from emp where job in (‘SALSMAN’, ‘MANAGER’); select ename, job from emp where sal in (1000, 5000);//in后面的值不是区间,是具体的值. not in:不是这几个值的. 模糊查询like: 找出名字当中含有o的? (在模糊查询中,必须掌握两个特殊的符号,%,代表任意多个字符,\_代表任意一个字符) select ename from emp where ename like ‘%o%’; 找出名字中第二个祖母是A的? select ename from emp where ename like ‘\_A%’; 找出名字中有下划线的?(使用转义字符’’) select ename from emp where ename like ‘%\_%’; 找出名字中最后一个字母是T的? select ename from emp where ename like ‘%T’; 13.排序 注意:默认是升序. 怎么制定升序或者降序? asc表示升序,desc表示降序. select ename, sal from emp order by sal;//升序 select ename, sal from emp order by sal asc;//升序 select ename, sal from emp order by sal desc;//降序 asc:ascend desc:descend 按照工资降序排列,当工资相同的时候再按照名字升序排列? select ename, sal from emp order by sal desc, ename asc; 注意:越靠前的字段越能起到主导作用.只有当前面的字段无法完成排序的时候,才会启用后面的字段. 找出工作岗位是SALESMAN的员工,并且要求按照薪资的降序排列? select ename, sal from emp where JOB = 'SALESMAN'order by sal desc; [重要] select * 步骤5 from tablename 步骤1 where 条件 步骤2 group by .. 步骤3 having .. 步骤4 order by ... 步骤6 1. 分组函数? count 计数 sum 求和 avg 平均值 max 最大值 min 最小值 记住:所有的分组函数都是对"某一组"数据进行操作的 找出工资总和? select sum(sal) from emp; 找出最高工作? select max(al) from emp; 找出最低工资? select min(sal) from emp; 找出平均工资? select avg(sal) from emp; 找出总人数? select count(ename) from emp; 分组函数只有5个.分组函数还有另一个名字:多行处理函数. 多行处理函数的特点是:输入多行,最终输出一行. 分组函数自动忽略NULL. 2. 单行处理函数 什么是单行处理函数? 输入一行, 输出一行. ifnull()函数 ifnull(可能为NULL的数据,被当做什么处理); select ename, ifnull(comm, 0) as comm from emp; 计算每个员工的年薪? 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 | ±-------±---------+ 修改: select ename, (sal + ifnull(comm, 0)) \* 12 as yearsal from emp; ±-------±---------+ | ename | yearsal | ±-------±---------+ | SMITH | 9600.00 | | ALLEN | 22800.00 | | WARD | 21000.00 | | JONES | 35700.00 | | MARTIN | 31800.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 | ±-------±---------+ \[重要\]规定:表达式中只要出现NULL, 结果一定是NULL 找出工资高于平均工资的员工? select ename, sal from emp where sal > avg(sal); //ERROR 1111 (HY000): Invalid use of group function 原因 Sql语句中有一个语法规则,分组函数不直接使用在where自居当中. 解释: 因为group by是在where执行之后才会执行. select(*)和select(某个字段)的区别? select(*)统计的是记录条数. select(某个字段)统计的是这个字段(不为空)的条数. 找出每个工作岗位的最高薪资. select max(sal) from emp group by job; 注意:分组函数一般都会和group by联合使用,这也是为什么他被称为分组函数的原因. 并且任何一个分组函数都是在group by语句执行结束之后执行的. 当一条语句没有 group by的话,整张表的数据自成一组. group by是在where之后执行的. 找出工资高于平均工资的员工? 找出平均工资 select avg(sal) from emp; ±------------+ | avg(sal) | ±------------+ | 2073.214286 | ±------------+ 用where划分 select ename, sal from emp where sal > 2073.214286; 如何写成一句? select ename, sal from emp where sal > (select avg(sal) from emp); 当一个语句有group by的话,select后面只能跟分组函数和参与分组的字段. (mysql语法松散,不会报错,但是oracle会报错) 找出每个部门不同工作岗位的最高薪资. select deptno, JOB, max(sal) from emp group by deptno, JOB; having 如果想对分组数据在进行过滤需要使用就having 找出每个部门的最高薪资,要求显示薪资大于2900的数据. 第一步:找出每个部门的最高薪资. select max(sal), deptno from emp group by deptno; 第二步: 找出薪资大于2900 的员工 mysql> select max(sal), deptno from emp group by deptno having max(sal) > 2900; (这种方案效率较低) mysql> select max(sal), deptno from emp where sal > 2900 group by deptno; (where比group by提起那执行,减少了查询记录的条数,效率较高) 找出每个部门的平均薪资,要求显示薪资大于2000的数据. 第一步:找出每个部门的平均薪资. mysql> select deptno, avg(sal) from emp group by deptno; 第二步:要求显示薪资大于2000 的数据. where后面不能用分组函数, 所以这里只能用having mysql> select deptno, avg(sal) from emp group by deptno having avg(sal) > 2000; 3. 总结一个完整的DQL语句 select 5 … from 1 … where 2 … group by 3 … having 4 … order by 6 … 4. 关于查询结果集的去重? select distinct job from emp; select ename, distinct job from emp; 上面这个sql语句是错误的. distinct只能出现在所有字段的最前面. select distinct deptno, job from emp; 注意:distinct 后面所有的字段组合在一起,去除重复记录. 5. 连接查询 19.1 什么是连接查询? 多张表联系起来查询 在实际开发中,大部分的情况下都不是从单表中查询数据,一般都是多张表联合查询去除最终的结果。 在实际开发中,一般一个业务都会对应多张表,比如:学生和班级,至少有两张表。 ## stuno stuname classeno classname ## 1 zs 1 实验高一1班 2 ls 2 实验高一2班 … (向上面这张表)学生和班级信息存储到一张表中,结果就像上面一样,数据会存在大量的重复, 导致数据的冗余(冗余的一种解释就是相同数据的重复出现) 19.2 连接查询的分类? 根据语法出现的年代划分,包括: SQL92(一些老的DBA可能还在使用这种语法。DBA:DataBase Administrator 数据库管理员) SQL99(比较新的语法) 根据表的连接方式来划分,包括: 内连接: 等值连接(按照取值相等来连接) 非等值连接 自连接(自己连接自己,把一张表看成两张或者若干张) 外连接: 左外连接(左连接) 右外链接(右链接) 全连接(这个不讲,很少用) 19.3 在表的连接查询方面有一种现象被称为:笛卡尔积现象(笛卡尔乘积现象) 案例: 找出每一个员工的部门名称,要求显示员工名和部门名. EMP表(部分) mysql> select ename, deptno from emp; +--------+--------+ | ename | deptno | +--------+--------+ | SMITH | 20 | | ALLEN | 30 | | WARD | 30 | | JONES | 20 | | MARTIN | 30 | | BLAKE | 30 | | CLARK | 10 | | SCOTT | 20 | | KING | 10 | | TURNER | 30 | | ADAMS | 20 | | JAMES | 30 | | FORD | 20 | | MILLER | 10 | +--------+--------+ dept表 mysql> select * from dept; +--------+------------+----------+ | DEPTNO | DNAME | LOC | +--------+------------+----------+ | 10 | ACCOUNTING | NEW YORK | | 20 | RESEARCH | DALLAS | | 30 | SALES | CHICAGO | | 40 | OPERATIONS | BOSTON | +--------+------------+----------+ 若这么写: mysql> select ename, dname from emp, dept; +--------+------------+ | ename | dname | +--------+------------+ | SMITH | ACCOUNTING | | SMITH | RESEARCH | | SMITH | SALES | | SMITH | OPERATIONS | | ALLEN | ACCOUNTING | | ALLEN | RESEARCH | | ALLEN | SALES | | ALLEN | OPERATIONS | | WARD | ACCOUNTING | | WARD | RESEARCH | | WARD | SALES | | WARD | OPERATIONS | | JONES | ACCOUNTING | | JONES | RESEARCH | | JONES | SALES | | JONES | OPERATIONS | | MARTIN | ACCOUNTING | | MARTIN | RESEARCH | | MARTIN | SALES | | MARTIN | OPERATIONS | | BLAKE | ACCOUNTING | | BLAKE | RESEARCH | | BLAKE | SALES | | BLAKE | OPERATIONS | | CLARK | ACCOUNTING | | CLARK | RESEARCH | | CLARK | SALES | | CLARK | OPERATIONS | | SCOTT | ACCOUNTING | | SCOTT | RESEARCH | | SCOTT | SALES | | SCOTT | OPERATIONS | | KING | ACCOUNTING | | KING | RESEARCH | | KING | SALES | | KING | OPERATIONS | | TURNER | ACCOUNTING | | TURNER | RESEARCH | | TURNER | SALES | | TURNER | OPERATIONS | | ADAMS | ACCOUNTING | | ADAMS | RESEARCH | | ADAMS | SALES | | ADAMS | OPERATIONS | | JAMES | ACCOUNTING | | JAMES | RESEARCH | | JAMES | SALES | | JAMES | OPERATIONS | | FORD | ACCOUNTING | | FORD | RESEARCH | | FORD | SALES | | FORD | OPERATIONS | | MILLER | ACCOUNTING | | MILLER | RESEARCH | | MILLER | SALES | | MILLER | OPERATIONS | +--------+------------+ 结论: 会产生 14 * 4 = 56 条记录, 也就是说第一个表的每一条查询记录都会和第二张表的所有查询记录组合成一条新的查询记录. 笛卡尔积现象:当两张表进行连接查询的时候,没有任何条件进行限制,最终的查询结果是两张表查询结果的记录条数的乘积. 关于表的别名: select e.ename, d.dname from emp e, dept d; 表的别名的好处都有啥? 第一: 执行效率高. 第二: 可读性好. 第三: 防止两张表出现相同的字段名. 19.4 如何避免笛卡尔积现象? 当然是加条件进行过滤. 思考: 避免了笛卡尔积现象,会减少记录的匹配次数吗? 不会,底层还是匹配了56次, 只不过显示的是有效记录. 案例: 找出每一个员工的部门名层,要求显示员工名和部门名. select e.ename, d.dname from emp e, dept d where e.deptno = d.deptno; mysql> select -> e.ename, d.dname -> from -> emp e, dept d -> where -> e.deptno = d.deptno; +--------+------------+ | 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 | +--------+------------+ 14 rows in set (0.00 sec) 19.5 内连接的等值连接,最大特点是: 条件是等量关系. 案例: 找出每一个员工的部门名层,要求显示员工名和部门名. SQL92(太老,不用): select e.ename, d.dname from emp e, dept d where e.deptno = d.deptno; SQL99(常用): select e.ename, d.dname from emp e (inner) join //inner可以省略,加上可以清楚地知道是内连接. dept d on e.deptno = d.deptno; SQL99和SQL92相比,其优点是:语法结构更加清晰,表的连接条件和后来的where条件更加清晰. 19.6 非等值连接查询 案例:找出每个员工的工资等级,要求显示员工名字,工资和工资等级 mysql>select ename sal from emp; mysql>select \* from salgrade; 正确答案: select e.ename, e.sal, s.grade from emp e inner join //inner可以省略,因为也是内连接 salgrade 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 | +--------+---------+-------+ 14 rows in set (0.05 sec) 19.7 自连接:把一张表看成两张表 案例: 找出每个员工的上级领导,要求显示员工名和对应的领导名. 把emp 命名成 a表, a表看成是员工表. 把emp 命名成 b表, b表看成是领导表. select a.ename as '员工名', b.ename as '领导名' from emp a inner join emp b on a.mgr = b.empno; //员工表的领导编号 和 领导表的员工编号对比.(能理解吧) 19.8 外连接 什么是外连接,和内连接有什么区别? 内连接: 假设A和B表进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询出来,这就是 内连接.AB两张表没有主副之分,两张表示平等的. 外连接: 假设A和B表进行连接,使用外连接的话,AB两张表中有一张表是主表,一张表是副表,主要查询主表中的 数据,捎带着查询副表,当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL与之匹配 外连接的分类? 左外连接(左连接):表示左边的这张表是主表 右外链接(右链接):表示右边的这张表是主表 左连接有右连接的写法,右连接有左连接的写法. 案例:找出每个员工的上级领导?(所有员工必须全部查询出来) 左连接写法: select a.ename as '员工', b.ename as '领导' from emp a left outer join //outer可以省略不写 emp b on a.mgr = b.empno; 右连接写法: select a.ename as '员工', b.ename as '领导' from emp b right outer join //outer可以省略不写 emp a on a.mgr = b.empno; +--------+-------+ | 员工 | 领导 | +--------+-------+ | SMITH | FORD | | ALLEN | BLAKE | | WARD | BLAKE | | JONES | KING | | MARTIN | BLAKE | | BLAKE | KING | | CLARK | KING | | SCOTT | JONES | | KING | NULL | //注意这里的NULL | TURNER | BLAKE | | ADAMS | SCOTT | | JAMES | BLAKE | | FORD | JONES | | MILLER | CLARK | +--------+-------+ 14 rows in set (0.00 sec) 区份内连接和外连接的关键是看有没有left和right 外连接最重要的特点:主表的数据无条件的全部查询出来. 案例:找出哪个部门没有员工? 左外连接更容易理解(外连接本质还是表的连接,会发生笛卡尔积现象) mysql> select -> d.* -> from -> dept d -> left outer join -> emp e -> on d.deptno = e.deptno -> where -> e.empno is null; +--------+------------+--------+ | DEPTNO | DNAME | LOC | +--------+------------+--------+ | 40 | OPERATIONS | BOSTON | +--------+------------+--------+ 19.9 全连接:两张表都是主表 19.10 三张表怎么连接查询?(多表连接) 案例:找出每一个员工的部门名称以及工资等级. 注意,解释一下: ... A join B join C on ... 表示:A表和B表先进行表连接,得到的结果在和表C进行表连接. select e.ename, d.dname, s.grade from emp e inner join dept d inner join salgrade s on e.deptno = d.deptno where e.sal between s.losal and s.hisal; 20.1 什么是子查询?子查询都可以出现在哪里? select语句当中嵌套select语句,被嵌套的select语句是子查询. 子查询可以出现在哪里? select …(select)… from …(select)… where …(select)… 20.2 where子句中使用子查询 案例: 找出高于平均薪资的员工信息. 第一步,找出平均薪资 select avg(sal) as 'avg' from emp; 第二步,找出高于平均薪资的员工信息 select ename, sal from emp where sal > (select avg(sal) as 'avg' from emp); 20.3 from后面嵌套子查询(important) 案例:找出每个部门平均薪水的薪资等级; 第一步:找出每个部门的平均薪水 select e.deptno, avg(e.sal) from emp e group by depno; 第二部分:将第一部分得到的临时表和salgrade表做表连接 select ntab.deptno, s.grade from (select e.deptno, avg(sal) as avg from emp e group by deptno) ntab //表的嵌套,括号里面没有';' inner join salgrade s on ntab.avg between s.losal and s.hisal; 案例:找出每个部门薪资等级的平均值 (可以用表的嵌套,但是没必要) 第一步:找出每个员工的薪资等级 select e.ename, e.deptno, s.grade, from emp e inner join salgrade s on e.sal between s.losal and s.hisal; 第二步:其实可以直接在第一步的语句后面用group by deptno求grade的平均值 select e.deptno, avg(s.grade) from emp e inner join salgrade s on e.sal between s.losal and s.hisal group by e.deptno; 表的嵌套的写法: select t.deptno, avg(t.grade) from (select e.ename as 'ename', e.deptno as 'deptno', s.grade as 'grade' from emp e inner join salgrade s on e.sal between s.losal and s.hisal) t group by t.deptno; (这么写其实有点多此一举了,deptno和grade在同一张表里面,不需要再把它看成临时表进行嵌套查询了,直接group by就行,之前一根筋只想着用嵌套了) 20.4 在select后面嵌套子查询 案例:找出每个员工所在的部门名称,要求显示员工和部门名称 内连接的写法: select e.ename, d.dname as '部门名称' from emp e inner join deptno d on e.deptno = d.deptno; 嵌套查询的写法:(不推荐写,不好理解) select e.ename, (select d.dname from dept d where e.deptno = d.deptno) as dname from emp e; 21 找出工作岗位是SALESMAN和MANAGER的员工 union可以连接两个不相干的查询结果,但是必须保证两个查询结果的列数相同 union可以完成where不能完成的工作 第一种: select ename, job from emp where job = 'MANAGER' or job = 'SALESMAN'; 第二种: select ename, job from emp where job in('MANAGER', 'SALESMAN'); 第三种(union写法): select ename, job from emp where job = 'MANAGER' union select ename, job from emp where job = 'SALESMAN'; mysql> select ename from emp -> union -> select dname from dept; +------------+ | ename | +------------+ | SMITH | | ALLEN | | WARD | | JONES | | MARTIN | | BLAKE | | CLARK | | SCOTT | | KING | | TURNER | | ADAMS | | JAMES | | FORD | | MILLER | | ACCOUNTING | | RESEARCH | | SALES | | OPERATIONS | +------------+ 结论:union的结果的表头(ename)只显示第一个查询结果的表头 22 limit(重点中的重点,以后分页查询全靠它) 22.1 limit是mysql特有的,其他数据库中没有,不通用. (Oracle中有一个相同的机制,叫做rownum) 22.2 limit取结果集中的部分数据,这是他的作用 22.3 语法机制: limit startIndex, length startIndex表示起始位置,从0开始,0表示第一条数据,startIndex可以省略,表示默认从第一条数据开始取 length表示取出几个数据 案例:取出工资前5名的员工(思路:降序取前5) 第一种写法: select ename, sal from emp order by sal desc limit 0, 5; 第二种写法: select ename, sal from emp order by sal desc limit 5; 22.4 limit是sql语句最后执行的一个环节: select 5 ... from 1 ... where 2 ... group by 3 ... having 4 ... order by 6 ... limit 7 ...; 22.5 案例:找出员工工资在第4到底9名的员工 mysql> select -> ename, sal -> from -> emp -> order by -> sal desc -> limit -> 3, 6; +--------+---------+ | ename | sal | +--------+---------+ | JONES | 2975.00 | | BLAKE | 2850.00 | | CLARK | 2450.00 | | ALLEN | 1600.00 | | TURNER | 1500.00 | | MILLER | 1300.00 | +--------+---------+ 22.6 通用的标准分页sql? 每页显示3条记录: 第1页:0, 3 第2页:3, 3 第3页:6, 3 第4页:9, 3 第5页:12, 3 每页显示pageSize条记录: 第pageNo页: (pageNo - 1) * pageSize, pageSize
还没有评论,来说两句吧...