MySQL牛刀小試的練習

首先了解下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 **/
相關文章
相關標籤/搜索