首先了解下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 **/