首先了解下sql语句底层执行顺序:html
select 5 from 1 where 2 group by 3 having 4 order by 6
下面开始进行一些MySQL试题训练,这些题目都是网上找到的,不过那个版本使用Oracle数据库写的答案,学数据库的应该都知道,MySQL与Oracle的语句仍是有些差异的。如下是我本身根据环境和题目写的。 环境的话本身能够搭建一个,数据库表我贴出来了仅供使用,内容以下:
/* SQLyog Ultimate v11.22 (64 bit) MySQL - 5.0.67-community ********************************************************************* */ /*!40101 SET NAMES utf8 */; #复制此文件内全部内容执行,建立Company数据库和数据。 CREATE DATABASE company; Use company; create table `dept` ( `deptno` int (2), `dname` varchar (60), `loc` varchar (60), primary key(deptno), index dept_index(deptno) )ENGINE=INNODB DEFAULT CHARSET=utf8; insert into `dept` (`deptno`, `dname`, `loc`) values('10','ACCOUNTING','NEW YORK'); insert into `dept` (`deptno`, `dname`, `loc`) values('20','RESEARCH','DALLAS'); insert into `dept` (`deptno`, `dname`, `loc`) values('30','SALES','CHICAGO'); insert into `dept` (`deptno`, `dname`, `loc`) values('40','OPERATIONS','BOSTON'); CREATE TABLE `emp` ( `empno` INT (4) primary key, `ename` VARCHAR (60), `job` VARCHAR (30), `mgr` INT (4), `hiredate` DATE , `sal` FLOAT , `comm` FLOAT , `deptno` INT (2), index emp_index(deptno), foreign key(deptno) references dept(deptno) on delete cascade on update cascade )ENGINE=INNODB DEFAULT CHARSET=utf8; INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7369','SMITH','CLERK','7902','1980-12-17','800.00',NULL,'20'); INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7499','ALLEN','SALESMAN','7698','1981-02-20','1600.00','300.00','30'); INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7521','FORD','SALESMAN','7698','1981-02-22','1250.00','500.00','20'); INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7566','JONES','MANAGER','7839','1981-04-02','2975.00',NULL,'20'); INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7654','MARTIN','SALESMAN','7698','1981-09-28','1250.00','1400.00','30'); INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7698','BLAKE','MANAGER','7839','1981-05-01','2850.00',NULL,'30'); INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7782','CLARK','MANAGER','7839','1981-06-09','2450.00',NULL,'10'); INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7788','SCOTT','ANALYST','7566','1987-04-19','3000.00',NULL,'20'); INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7839','KING','PRESIDENT',NULL,'1981-11-17','5000.00',NULL,'10'); INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7844','TURNER','SALESMAN','7698','1981-09-08','1500.00','0.00','30'); INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7876','ADAMS','CLERK','7788','1987-05-23','2200.00',NULL,'20'); INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7900','JAMES','CLERK','7698','1981-12-03','950.00',NULL,'30'); INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7902','FORD','ANALYST','7566','1981-12-03','3000.00',NULL,'20'); INSERT INTO `emp` (`empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES('7934','MILLER','CLERK','7782','1982-01-23','1300.00',NULL,'10'); create table `salgrade` ( `grade` int (1) primary key, `losal` float , `hisal` float ); insert into `salgrade` (`grade`, `losal`, `hisal`) values('1','700.00','1200.00'); insert into `salgrade` (`grade`, `losal`, `hisal`) values('2','1201.00','1400.00'); insert into `salgrade` (`grade`, `losal`, `hisal`) values('3','1401.00','2000.00'); insert into `salgrade` (`grade`, `losal`, `hisal`) values('4','2001.00','3000.00'); insert into `salgrade` (`grade`, `losal`, `hisal`) values('5','3001.00','9999.00');
废话很少说,开练吧!
-- 1.查询emp表,显示薪水大于2000,且工做类别是MANAGER的雇员信息mysql
select * from emp where sal > 2000 and job = 'MANAGER';
-- 2.查询emp表,显示年薪大于30000,工做类别不是MANAGER的雇员信息sql
select * from emp where job <> 'MANAGER' and sal*12+ifnull(comm,0) > 30000; /*ifnull(值1,值2) 当值1非空,显示它自己的值即值1,当值1为空null,显示值2的值.因此这里的意思是当comm的值为空时,显示值2也就是0
-- 3.查询emp表, 显示薪水在1500到3000之间,工做类别以“M”开头的雇员信息数据库
select * from emp where sal between 1500 and 3000 and job like 'M%'; /* like是模糊查询,%匹配任意字符,只要开头是M的字符都在统计范围。 若是是'M_',那就是匹配已M开头的两个字符长度的数值
-- 4.查询emp表,显示佣金为空而且部门号为20或30的雇员信息oracle
select * from emp where comm is null and deptno in (20,30); /*in,是在什么内
-- 5.查询emp表,显示佣金不为空或者部门号为20的雇员信息,要求按照薪水降序排列ide
select * from emp where comm is not null and deptno=20 order by sal desc; /*不等于也能够用<>,!=
-- 6.查询emp表,显示年薪大于30000工做类别不是MANAGER,且部门号不是10或40的雇员信息,要求按照雇员姓名进行排列函数
select * from emp where 12*sal+ifnull(comm,0)>30000 and job <>'MANAGER' and deptno not in (10,40) order by ename ; /*order by 是排序,因为默认是升序,因此asc可加或不加,desc是倒序。 order by string asc/desc,两个字段以上可用逗号分隔
-- 7.查询EMP、DEPT表,输出的列包含员工姓名、工资、部门编号、部门名称、部门地址.工具
select ename,sal,a.deptno,dname,loc from emp a,dept b where a.deptno=b.deptno; /*a和b的做用相似于别名,这样能够区分不一样表之间相同的列名。
-- 8.使用自链接查询EMP表,输出的列包含员工姓名、主管姓名.code
select boss.ename 老板,works.ename 员工 from emp boss,emp works where boss.mgr=works.empno;
-- 9.在上一题的基础上,思考下为何输出结果没有KING的信息? 若是要输出KING的信息,如何修改?orm
select boss.ename 老板,works.ename 员工 from emp boss left join emp works on boss.mgr=works.empno; /*emp boss与emp works交换位置的话,就能够用右连接right join ... on
-- 10.使用左链接查询员工部门,包括没有员工的部门信息,输出列:部门编号、部门名称、位置。 --(左表为dept表,emp为右表)
select a.deptno,dname,loc from dept a left join emp b on a.deptno=b.deptno;
-- 11.查询EMP表,输出每一个部门的平均工资,并按部门编号降序排列.
select deptno,avg(sal) from emp group by deptno ORDER BY deptno desc;
-- 12.查询EMP表,输出每一个职位的平均工资,按平均工资升序排列.
select job,avg(sal) as sal_avg from emp group by job order by sal_avg; /*as后面跟的是别名,这样order by后面也能够根别名来排序
-- 13.查询EMP表,输出每一个部门的各个职位的平均工资,并按部门编号升序、平均工资降序排序。
select deptno,job,avg(sal) from emp group by deptno,job order by deptno,avg(sal) desc;
-- 14.使用子查询,找出哪一个部门下没有员工
方法1: select * from dept where deptno <> all (select deptno from emp); 方法2: select * from dept where deptno not in (select deptno from emp);
-- 15.使用子查询,找出那些工资低于全部部门的平均工资的员工
select * from emp where sal < all (select avg(sal) from emp GROUP BY deptno); /*当子查询返回多个结果时,只能用in/any/all。 any是任意,all是所有
-- 16.使用子查询,找出那些工资低于任意部门的平均工资的员工,比较一下与上一题输出的结果是否相同?
select * from emp where sal < any (select avg(sal) from emp GROUP BY deptno);
-- 17.在EMP表中,增长一名员工,员工信息参照现有员工构造.
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(8999,'zhang','manager',null,now(),7000,2000,10); /*若是是全表插入,那表结构可不写,直接写值values就行
-- 18.员工SMITH部门调动到SALES部门,请编写SQL语句更新员工信息.
update emp set deptno= (select deptno from dept where dname='SALES') where ename='SMITH'; /*这里要注意,MySQL不能删除或更新与子查询同样的表,不然会报错。也就是子查询中的表不能与修改的表相同。Oracle没这个限制。可是MySQL遇到这种状况时只要在套一层便可,具体方法最后后面会有题目遇到。
-- 19.员工JAMES已经离职,请编写SQL语句更新数据库.
delete from emp where ename='james';
-- 20.用户执行delete from emp;语句删除了EMP表的记录,但没有提交,请问有办法恢复EMP原来的数据吗?
答: navicat工具是直接删除了,最好别操做。每次更新或删除操做前切记都进行备份。
-- 21.获得平均工资大于2000的工做职种
select job,avg(sal) from emp group by job having avg(sal) > 2000;
-- 22.分部门获得工资大于2000的全部员工的平均工资,而且平均工资还要大于2500
select deptno,avg(sal) from emp where sal>2000 group by deptno having avg(sal)>2500;
-- 23.获得每月工资总数最少的那个部门的部门编号,部门名称,部门位置
select a.deptno,b.dname,b.loc,sum(sal) from emp a, dept b where a.deptno=b.deptno group by a.deptno,b.dname order by sum(sal) limit 1; /*排序取一行
-- 24.分部门获得平均工资等级为2级(等级表)的部门编号
select deptno,grade,avg(sal) from emp,salgrade where sal between losal and hisal and grade=2; group by deptno
-- 25.查找出部门10和部门20中,工资最高第3名到工资第5名的员工的员工名字,部门名字,部门位置
select a.deptno,ename,dname,loc,sal from emp a,dept b where a.deptno=b.deptno and a.deptno in (10,20) order by sal desc limit 2,3; /*limit 数值1,数值2 数值1:0 表明从第一行开始取值 1 表明从第二行开始取值 数值2:表明取多少行记录*/
-- 26.查找出收入(工资加上奖金),下级比本身上级还高的员工编号,员工名字,员工收入
select a.ename,a.empno,a.sal
from emp a,emp aa
where a.mgr=aa.empno
and a.sal+ifnull(a.comm,0)>aa.sal+IFNULL(aa.comm,0);
-- 27.查找出职位和'MARTIN' 或者'SMITH'同样的员工的平均工资 */
select job,avg(sal) from emp where job in (select job from emp where ename in ('MARTIN','SMITH')) GROUP BY job;
-- 28.查找出不属于任何部门的员工
select * from dept where deptno not in (select deptno from emp);
-- 29.按部门统计员工数,查出员工数最多的部门的第二名到第五名(列出部门名字,部门位置)
select a.deptno,count(ename),b.loc from emp a, dept b where a.deptno=b.deptno GROUP BY deptno order by count(ename) desc limit 1,4;
-- 30.查询出king所在部门的部门号\部门名称\部门人数
select count(1),dname,a.deptno from emp a,dept b where a.deptno=b.deptno and a.deptno = (select deptno from emp where ename='king');
-- 31.查询出king所在部门的工做年限最大的员工名字
select hiredate,ename from emp where deptno =(select deptno from emp where ename='king') ORDER BY hiredate limit 1;
-- 32.查询出工资成本最高的部门的部门号和部门名称
select a.deptno,dname,sum(sal) from emp a , dept b where a.deptno=b.deptno group by deptno ORDER BY sum(sal) desc limit 1;
-- 33.显示全部员工的姓名、工做和薪金,按工做的降序排序,若工做相同则按薪金排序.
select ename,job,sal from emp order by job desc,sal;
-- 34.显示全部员工的姓名、加入公司的年份和月份,按受雇日期所在月排序,若月份相同则将最先年份的员工排在最前面.
select ename,DATE_FORMAT(hiredate,'%Y') years,date_format(hiredate,'%m') months from emp ORDER BY months,years;
-- 35.显示在一个月为30天的状况全部员工的日薪金,忽略余数
select *,sal*12/360 sal_day from emp;
-- 36.找出在(任何年份的)2月受聘的全部员工。
select * from emp where date_format(hiredate,'%m')=2;
-- 37.对于每一个员工,显示其加入公司的天数.
select ename,hiredate,date(now()) 当前日期,DATEDIFF(now(),hiredate) 入职天数 from emp; /*datadiff(str1,str2) str1-str2等于当前天数,日期天数计算函数
-- 38.显示姓名字段的任何位置包含"A"的全部员工的姓名.select * from emp where ename like '%A%';
-- 39.以年月日的方式显示全部员工的服务年限.
-- 年
select *,datediff(now(),hiredate)/365 年 from emp;
-- 月
select *,datediff(now(),hiredate)/30 月 from emp;
-- 日
select *,datediff(now(),hiredate) 天数 from emp;
-- 40.显示员工的姓名和受雇日期,根据其服务年限,将最老的员工排在最前面.
select ename,hiredate,datediff(now(),hiredate)/365 年限 from emp order by 年限 desc;
-- 43.对emp表中sal、comm进行加计算,并使用别名命令为员工的月总收入,同时展现出员工部门编号、员工姓名信息。
select deptno,ename,sal+ifnull(comm,0) as 月总收入 from emp;
-- 44.使用链接符查询emp表中员工的姓名和工资,并以以下格式列出且字段名展现为 TOTAL INCOME:
select concat(ename,sal) as "TOTAL INCOME" from emp;
-- 45.使用distinct排重查询emp中的job类型
select distinct job from emp;
-- 46.从emp表中找出奖金高于 薪水60%的员工
select ename from emp where ifnull(comm,0)>0.6*sal;
-- 47.找出部门10中全部经理(MANAGER)和部门20中全部办事员(CLERK)的详细资料。
select * from emp where deptno=10 and job ='MANAGER' or deptno=20 and job='CLERK';
-- 48.从emp和dept中联合查询,并将员工编号、姓名、职位、地址信息列出。
select empno,ename,job,loc from emp a,dept b where a.deptno=b.deptno;
-- 49.统计各部门的薪水总和。
select deptno,sum(sal) from emp GROUP BY deptno;
-- 50.找出部门10中全部理(MANAGER),部门20中全部办事员(CLERK)以及既不是经理又不是办事员但其薪水大于或等2000的全部员工的详细资料。
select * from emp where job='MANAGER' and deptno=10 or job='CLERK' and deptno=20 or job not in ('MANAGER','CLERK') and sal>2000 ;
-- 51.列出各类工做的最低工资。
select job,min(sal) from emp group by job;
-- 52.列出各个部门的MANAGER(经理)的最低薪水。
select deptno,job,min(sal) from emp where job='MANAGER' group by deptno;
-- 53.列出有奖金的员工的不一样工做。
select * from emp where comm is not null;
-- 54.找出无奖金或奖金低于300的员工。
select * from emp where comm is null or comm<300;
-- 55.显示全部员工的姓名,并使姓名首字母大写。
oracle有initcap函数 select initcap(ename) from emp;
-- 56.显示正好为5个字符的员工的姓名。
select * from emp where length(ename)=5;
-- 57.显示不带有“R”的员工姓名。
select * from emp where ename not like '%R%';
-- 58.列出薪水高于在部门30工做的全部员工的薪水的员工姓名和薪水。
select * from emp where sal > all(select sal from emp where deptno=30);
-- 59.列出在每一个部门工做的员工数量、平均工资和平均服务期限。
select deptno,count(ename) as 员工数量,avg(sal) as 平均薪资,avg(datediff(now(),hiredate)/365) as 平均年限 from emp group by deptno;
-- 60.列出从事同一种工做但属于不一样部门的员工的一种组合。
select * from emp a , emp b where a.job = b. job and a.deptno <> b.deptno ;
-- 61.列出薪水比“SMITH”多的全部员工。
select * from emp where sal > (select sal from emp where ename='SMITH');
-- 62.列出至少有一个员工的全部部门。
select deptno,count(ename) as 员工 from emp group by deptno having 员工>1;
-- 63.对于每一个员工,显示其加入公司的天数、月数、年数。
select ename,datediff(sysdate(),hiredate)/365 as 年, datediff(now(),hiredate)/30 as 月,datediff(now(),hiredate) as 天 、 from emp; /*SYSDATE()与NOW(),显示当前系统时间
-- 64.对上题中的天数、月数、年数取整显示。
方法1: select ename,round(datediff(sysdate(),hiredate)/365) as 年, round(datediff(now(),hiredate)/30) as 月,datediff(now(),hiredate) as 天 from emp; /* round() 四舍五入法 */ 方法2: select ename,truncate(datediff(sysdate(),hiredate)/365,0) as 年, truncate(datediff(now(),hiredate)/30,0) as 月,datediff(now(),hiredate) as 天 from emp; /* truncate() 阶段函数*/
-- 65.找出在每一年5月受聘的全部员工。
select * from emp where date_format(hiredate,'%m')=5;
-- 66.显示在一个月为30天的状况下全部员工的日薪水,取整。
select ename,round(sal/30) as 日薪 from emp;
-- 67.显示全部员工的姓名和加入公司的年份和月份,并将员工入职年月从低到高排序。
select ename,date_format(hiredate,'%Y-%m') as 入职年月 from emp order by 入职年月;
-- 68.请查SMITH领导的薪水
方法1: select boss.sal from emp boss,emp works where boss.empno=works.mgr and works.ename='SMITH'; 方法2: select sal from emp where empno = (select mgr from emp where ename='SMITH');
-- 69.请查SMITH领导的薪水和所在的部门地址
select a.sal,b.loc from emp a ,dept b where a.deptno=b.deptno and a.empno = (select mgr from emp where ename='SMITH');
-- 70.请查SMITH领导的薪水和所在的部门地址 以及领导的薪水等级
select a.sal,b.loc,c.grade from emp a ,dept b, salgrade c where a.deptno=b.deptno and a.sal between losal and hisal and a.empno = (select mgr from emp where ename='SMITH');
-- 71.查出SMITH的薪水等级
select sal,grade from emp,salgrade where sal between losal and hisal and ename='SMITH';
-- 72.请查出SIMIH的薪水等级和他所在部门所在地
select sal,grade,loc from emp a,dept b,salgrade where sal between losal and hisal and a.deptno=b.deptno and a.ename='SMITH';
-- 73.按照职位分组,求出每一个职位的最大薪水
select job,max(sal) from emp group by job;
-- 74.
-- I)求出每一个部门中的每一个职位的最大薪水
select deptno,job,max(sal) from emp group by deptno,job;
-- II)在薪水大于1000,而且职位不是MANAGER的员工中,求职哪一个职位的平均薪水大于2000
select job,avg(sal) from emp where sal>1000 and job <> 'MANAGER' group by job;
-- 75.列出SMITH的薪水和职位
select ename,sal,job from emp where ename='SMITH';
-- 76.列出SMITH的部门地址和补贴和薪水等级(等级表salgrade)
select a.ename,b.loc,ifnull(comm,0) as 补贴,grade from emp a,dept b,salgrade where a.deptno=b.deptno and sal BETWEEN losal and hisal and ename='SMITH';
-- 77.列出部门不是10,职位不是C开头的,薪资比公司平均薪资都高的员工名字
select * from emp where deptno <>10 and job not like 'C%' and sal > (select avg(sal) from emp);
-- 78.哪一个部门下面没有员工
select a.ename,b.deptno from emp a right join dept b on a.deptno=b.deptno;
-- 79.谁的薪水比SMITH多,同时部门又是和SCOTT的部门相同
select * from emp where deptno = (select deptno from emp where ename='SCOTT') and sal > (select sal from emp where ename='SMITH');
-- 80.列出薪资比每一个部门每一个职位的平均薪资还要高的员工
select * from emp where sal >all (select avg(sal) from emp group by deptno);
-- 81.SMITH的职位变动为SCOTT的职位
update emp set job= (select b.job from (select job from emp where ename='SCOTT') b) where ename='SMITH'; /** You can't specify target table 'emp' for update in FROM clause mysql的子查询语句更新或删除不能在同一张表上,否则就会报这个错误。只要在套一层就解决啦。 参考: https://www.cnblogs.com/jeffen/p/7016547.html **/