数据库原始数据

DROP TABLE IF EXISTS EMP;
DROP TABLE IF EXISTS DEPT;
DROP TABLE IF EXISTS SALGRADE;

CREATE TABLE DEPT
       (DEPTNO int(2) not null ,
	DNAME VARCHAR(14) ,
	LOC VARCHAR(13),
	primary key (DEPTNO)
	);
CREATE TABLE EMP
       (EMPNO int(4)  not null ,
	ENAME VARCHAR(10),
	JOB VARCHAR(9),
	MGR INT(4),
	HIREDATE DATE  DEFAULT NULL,
	SAL DOUBLE(7,2),
	COMM DOUBLE(7,2),
	primary key (EMPNO),
	DEPTNO INT(2) 
	)
	;

CREATE TABLE SALGRADE
      ( GRADE INT,
	LOSAL INT,
	HISAL INT );




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'); 
commit;
 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7369, 'SMITH', 'CLERK', 7902,  '1980-12-17'
, 800, NULL, 20); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7499, 'ALLEN', 'SALESMAN', 7698,  '1981-02-20'
, 1600, 300, 30); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7521, 'WARD', 'SALESMAN', 7698,  '1981-02-22'
, 1250, 500, 30); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7566, 'JONES', 'MANAGER', 7839,  '1981-04-02'
, 2975, NULL, 20); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7654, 'MARTIN', 'SALESMAN', 7698,  '1981-09-28'
, 1250, 1400, 30); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7698, 'BLAKE', 'MANAGER', 7839,  '1981-05-01'
, 2850, NULL, 30); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7782, 'CLARK', 'MANAGER', 7839,  '1981-06-09'
, 2450, NULL, 10); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7788, 'SCOTT', 'ANALYST', 7566,  '1987-04-19'
, 3000, NULL, 20); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7839, 'KING', 'PRESIDENT', NULL,  '1981-11-17'
, 5000, NULL, 10); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7844, 'TURNER', 'SALESMAN', 7698,  '1981-09-08'
, 1500, 0, 30); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7876, 'ADAMS', 'CLERK', 7788,  '1987-05-23'
, 1100, NULL, 20); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7900, 'JAMES', 'CLERK', 7698,  '1981-12-03'
, 950, NULL, 30); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7902, 'FORD', 'ANALYST', 7566,  '1981-12-03'
, 3000, NULL, 20); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7934, 'MILLER', 'CLERK', 7782,  '1982-01-23'
, 1300, NULL, 10); 
commit;
 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
1, 700, 1200); 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
2, 1201, 1400); 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
3, 1401, 2000); 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
4, 2001, 3000); 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
5, 3001, 9999); 
commit;
 

三张表

部门表:

员工表:

薪资登记表:

1.取每个部门最高薪水的人员名称

第一步:求每个部门的最高薪水

select deptno,max(sal) as maxsal from emp group by deptno;

结果:

第二步:将求出的表和emp进行连接

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、哪些人的薪水在部门的平均薪水之上 

第一步:求每个部门的平均薪水

select deptno,avg(sal) as avgsal from emp group by deptno;

结果:
第二步:所求表当做临时表t 和 emp 表进行连接,条件为

SELECT
e.ename,e.sal,t.*
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;

结果:

3、取得部门中(所有人的)平均的薪水等级


平均的薪水等级:先计算每个薪水的等级,
                            然后找出薪水等级的平均值

平均薪水的等级:先计算平均薪水,然后找出薪水的等级值

第一步:第一步:计算每个人的薪水等级
思路:涉及到二张表,一个是员工表,一个是等级表

SELECT 
e.ename,e.sal,e.deptno,s.grade
FROM
emp e
JOIN
salgrade s
ON
e.sal BETWEEN s.losal AND s.hisal;

第二步:根据上表的基础上进行分组

select
e.deptno,avg(s.grade)
from
emp e
join
salgrade s
on
e.sal BETWEEN s.losal AND s.hisal
group by
e.deptno;

 

 4.不准用函数取得最高薪水

思路:order by 排序加limit

SELECT 
ename,sal
FROM 
emp
ORDER BY
sal
DESC
LIMIT
1;

 5、取得平均薪水最高的部门的部门编号

我的思路:
第一步:求每个部门的平均薪水

select 
deptno,avg(sal)
from
emp
group by
deptno;

第二步:再上面的基础上 加上order BY 和limit

SELECT 
deptno,AVG(sal)AS avgsal
FROM
emp
GROUP BY
deptno
ORDER BY
avgsal
DESC
LIMIT
1;

需要注意的是mysql的执行顺序

  1. from 
  2. join 
  3. on 
  4. where 
  5. group by(开始使用select中的别名,后面的语句中都可以使用)
  6.  avg,sum.... 
  7. having 
  8. select 
  9. distinct 
  10. order by
  11. limit 

6、取得平均薪水最高的部门的部门名称

我的思路:
先求平均薪水最高的部门名称,肯定涉及了二张表的
的关联 emp和dept

SELECT 
AVG(e.sal) AS avgsal,d.dname
FROM
emp e
JOIN
dept d
ON
e.deptno=d.deptno
GROUP BY
d.dname
ORDER BY
avgsal
DESC
LIMIT
1;

 

7、求平均薪水的等级最低的部门的部门名称

平均薪水是800
平均薪水是900
那么他俩都是1级别。

第一步:找出每个部门的平均薪水
select deptno,avg(sal) as avgsal from emp group by deptno;
+--------+-------------+
| deptno | avgsal      |
+--------+-------------+
|     10 | 2916.666667 |
|     20 | 2175.000000 |
|     30 | 1566.666667 |
+--------+-------------+

第二步:找出每个部门的平均薪水的等级
以上t表和salgrade表连接,条件:t.avgsal between s.losal and s.hisal

select 
    t.*,s.grade
from
    (select d.dname,avg(sal) as avgsal from emp e join dept d on e.deptno = d.deptno group by d.dname) t
join
    salgrade s
on
    t.avgsal between s.losal and s.hisal;

+------------+-------------+-------+
| dname      | avgsal      | grade |
+------------+-------------+-------+
| SALES      | 1566.666667 |     3 |
| ACCOUNTING | 2916.666667 |     4 |
| RESEARCH   | 2175.000000 |     4 |
+------------+-------------+-------+

select 
    t.*,s.grade
from
    (select d.dname,avg(sal) as avgsal from emp e join dept d on e.deptno = d.deptno group by d.dname) t
join
    salgrade s
on
    t.avgsal between s.losal and s.hisal
where
    s.grade = (select grade from salgrade where (select avg(sal) as avgsal from emp group by deptno order by avgsal asc limit 1) between losal and hisal);

+-------+-------------+-------+
| dname | avgsal      | grade |
+-------+-------------+-------+
| SALES | 1566.666667 |     3 |
+-------+-------------+-------+

抛开之前的,最低等级你怎么着?
    平均薪水最低的对应的等级一定是最低的.
    select avg(sal) as avgsal from emp group by deptno order by avgsal asc limit 1;
    +-------------+
    | avgsal      |
    +-------------+
    | 1566.666667 |
    +-------------+

    select grade from salgrade where (select avg(sal) as avgsal from emp group by deptno order by avgsal asc limit 1) between losal and hisal;
    +-------+
    | grade |
    +-------+
    |     3 |
    +-------+
8、取得比普通员工(员工代码没有在 mgr 字段上出现的) 的最高薪水还要高的领导人姓名

比“普通员工的最高薪水”还要高的一定是领导!
        没毛病!!!!

求出所有领导的编号
SELECT DISTINCT mgr FROM emp WHERE mgr IS NOT NULL;

第一步:找出普通员工的最高薪水!
not in在使用的时候,后面小括号中记得排除NULL。
select max(sal) from emp where empno not in
(select distinct mgr from emp where mgr is not null);

 

第二步:找出高于1600的
select ename,sal from emp where sal > 
(select max(sal) from emp where empno not in
(select distinct mgr from emp where mgr is not null));

 

9、取得薪水最高的前五名员工

select
empno,ename,sal
from
emp
order by
sal
desc
limit
5;

 

 10、取得薪水最高的第六到第十名员工

select
empno,ename,sal
from
emp
order by
sal
desc
limit
5,5;

11、取得最后入职的 5 名员工

日期也可以进行升序,降序

select 
empno,ename,HIREDATE
from
emp
order by
HIREDATE
desc
limit
5;

12、取得每个薪水等级有多少员工

思路:需要将员工表和薪水等级表进行连接

第一步:求出每个员工的薪水等级
select 
e.empno,e.ename,e.sal,s.grade
from
emp e
join
salgrade s
on
e.sal 
between s.losal and s.hisal;

第二步:根据上面查询的结果,按照grade进行分组

SELECT 
s.grade,count(*)
FROM
emp e
JOIN
salgrade s
ON
e.sal 
BETWEEN s.losal AND s.hisal
group by
s.grade

14、列出所有员工及领导的姓名 

思路:自连接
SELECT
e.ename AS'员工',t.ename AS '领导'
FROM
emp e
JOIN
emp t
ON
e.mgr=t.empno;

 15、列出受雇日期早于其直接上级的
所有员工的编号,姓名,部门名称

第一步:
求出受雇日期早于员工上级的编号,姓名
应该要用到自连接
员工为a 领导为b
select 
a.empno,a.ename,a.deptno
from
emp a
join
emp b
on
a.mgr=b.empno
where
a.hiredate<b.hiredate;

第二步:在第一步的基础上,讲第一步的结果当成视图,
和dept进行连接
select
t.*,d.dname
from 
(select 
a.empno,a.ename,a.deptno
from
emp a
join
emp b
on
a.mgr=b.empno
where
a.hiredate<b.hiredate)t
join
dept d
on
t.deptno=d.deptno;

 16、 列出部门名称和这些部门的员工信息同时列出那些没有员工的部门

我的思路:应该是需要用到外连接了
需要将部门表和员工表进行连接,在这里使用左外连接
select
d.dname,e.*
from
dept d
left join
emp e
on
e.deptno=d.deptno;

 17、列出至少有 5 个员工的所有部门

SELECT
deptno
FROM
emp
GROUP BY
deptno
HAVING
COUNT(*)>=5;

一个完整的 select 语句格式如下
select 字段
from 表名
where …….
group by ……..
having …….(就是为了过滤分组后的数据而存在的不可以单独的出现)
order by ……..
以上语句的执行顺序
1. 首先执行 where 语句过滤原始数据
2. 执行 group by 进行分组
3. 执行 having 对分组数据进行操作
4. 执行 select 选出数据
5. 执行 order by 排序
原则:能在 where 中过滤的数据,尽量在 where 中过滤,效率较高。having 的过滤是专门对分组之后的数据进行过滤
的。

18、列出薪金比"SMITH" 多的所有员工信息

思路:用到了子查询

SELECT
*
FROM
emp
WHERE
sal>(SELECT sal FROM emp WHERE ename='SMITH');

 19、 列出所有"CLERK"( 办事员) 的姓名及其部门名称, 部门的人数

我的思路:第一步,先关联二张表,员工表和部门表
select 
e.ename,d.dname
from
emp e
join
dept d
on
e.deptno=d.deptno
where
e.job='CLERK';

第二步:求出每个部门的人数
select
deptno,count(*)as countdept
from
emp
group by
deptno;

第三步:将二张表关联
SELECT 
     t1.*,t2.countdept
FROM

(SELECT 
e.ename,d.dname,d.deptno
FROM
emp e
JOIN
dept d
ON
e.deptno=d.deptno
WHERE
e.job='CLERK') t1

JOIN

(SELECT
deptno,COUNT(*)AS countdept
FROM
emp
GROUP BY
deptno) t2

ON
t1.deptno=t2.deptno;

 

 20、列出最低薪金大于 1500 的
各种工作及从事此工作的全部雇员人数

SELECT job,COUNT(*) FROM emp GROUP BY job HAVING MIN(sal)>1500;

21、列出在部门"SALES"< 销售部> 工作的员工的姓名,
 假定不知道销售部的部门编号.

可以用子查询
 SELECT ename FROM emp WHERE 
deptno = 
(SELECT deptno FROM dept WHERE dname='SALES');
 

 

22、列出薪金高于公司平均薪金的所有员工, 所在部门, 上级领导, 雇员的工资等级.

涉及到多表查询 三表查询

select 
	e.ename '员工',d.dname,l.ename '领导',s.grade
from
	emp e
join
	dept d
on
	e.deptno = d.deptno
left join
	emp l
on
	e.mgr = l.empno
join
	salgrade s
on
	e.sal between s.losal and s.hisal
where
	e.sal > (select avg(sal) from emp);

 

  23、 列出与"SCOTT" 从事相同工作的所有员工及部门名称

思路:需要二张表 emp  dept
 select 
 a.empno,a.ename,b.dname
 from 
 emp a
 join
 dept b
 on
 a.deptno = b.deptno
 where
 JOB=
 (select JOB from emp where ename='SCOTT')
 and
 a.ename!='SCOTT';

 24、列出薪金等于
 部门 30 中员工的薪金的其他员工的姓名和薪金.

 select 
 ename,sal
 from
 emp
 where
 sal = (select sal from emp where deptno=30)
 and
 deptno!=30;

 

 SELECT 
 ename,sal
 FROM
 emp
 WHERE
 sal IN (SELECT sal FROM emp WHERE deptno=30)
 AND
 deptno!=30;

 其实就是将"="号 改为"IN"。
  原因是"="号的后面取的可以使具体的值也可以是空值,不是判断关键词,
  但是"IN"是会与后面的数据值进行判断的,可以作为判断关键词。

25、列出薪金高于在部门 30 
工作的所有员工的薪金的员工姓名和薪金. 部门名称

我的思路:第一步 求出部门30工作的所有员工的薪金(就是求最高薪金)
SELECT
MAX(sal)
FROM
emp
WHERE
deptno=30;

第二步:员工姓名和薪金,在emp表 当a 部门名称:dept 当b表
select
a.ename,a.sal,b.dname
from
emp a
join
dept b
on 
a.deptno=b.deptno
where
sal>(SELECT
MAX(sal)
FROM
emp
WHERE
deptno=30);

 

26、列出在每个部门工作的员工数量, 平均工资和平均服务期限

没有员工的部门,部门人数是0

SELECT 
	d.deptno, COUNT(e.ename) ecount,IFNULL(AVG(e.sal),0) AS avgsal, IFNULL(AVG(TIMESTAMPDIFF(YEAR, hiredate, NOW())), 0) AS avgservicetime
FROM
	emp e
RIGHT JOIN
	dept d
ON
	e.deptno = d.deptno
GROUP BY
	d.deptno;

在mysql当中怎么计算两个日期的“年差”,差了多少年?
    TimeStampDiff(间隔类型, 前一个日期, 后一个日期)
    
    timestampdiff(YEAR, hiredate, now())

    间隔类型:
        SECOND   秒,
        MINUTE   分钟,
        HOUR   小时,
        DAY   天,
        WEEK   星期
        MONTH   月,
        QUARTER   季度,
        YEAR   年

27、 列出所有员工的姓名、部门名称和工资。

我的思路:员工的姓名 和工资在emp 部门名称在dept 表连接
select 
        e.ename,e.sal,d.dname
from    
        emp e
join  
        dept d
on
        e.deptno=d.deptno;

 28、列出所有部门的详细信息和人数

我的思路:部门的详细信息 dept所有字段,和emp统计人数
select 
d.*,count(e.ename)as countname
from
emp e
right join
dept d
on
d.deptno=e.deptno
group by
d.deptno;

29、列出各种工作的最低工资及从事此工作的雇员姓名 

SELECT
job,MIN(sal)AS minsal
FROM
emp
GROUP BY
job;

select 
	e.ename,t.*
from
	emp e
join
	(select 
		job,min(sal) as minsal
	from
		emp
	group by
		job) t
on
	e.job = t.job and e.sal = t.minsal;

 

30、列出各个部门的 MANAGER( 领导) 的最低薪金 

select 
	deptno, min(sal)
from
	emp
where
	job = 'MANAGER'
group by
	deptno;

31、列出所有员工的 年工资, 按 年薪从低到高排序 

select 
	ename,(sal + ifnull(comm,0)) * 12 as yearsal
from
	emp
order by
	yearsal asc;

32、求出员工领导的薪水超过3000的员工名称与领导 

select
a.ename as '员工',b.ename as'领导'
from
emp a
join
emp b
on
a.mgr=b.empno
where
b.sal>3000;

33、求出部门名称中, 带'S'字符的部门员工的工资合计、部门人数

select 
	d.deptno,d.dname,d.loc,count(e.ename),ifnull(sum(e.sal),0) as sumsal
from
	emp e
right join
	dept d
on
	e.deptno = d.deptno
where
	d.dname like '%S%'
group by
	d.deptno,d.dname,d.loc;

 34、给任职日期超过 30 年的员工加薪 10%.

update emp set sal = sal * 1.1 where timestampdiff(YEAR, hiredate, now()) > 30;

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐