SQL练习题

新建数据表

首先建立测试数据库的表,新建数据库的sql语句如下,大家可以粘贴成一个sql文件,然后新建所有的表并插入所有的数据:

新建数据库sql文件:

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;
 

现在我们可以看到有3张表,分别是:emp(员工信息表)、dept(部门信息表)、salgrade(薪水等级表),三张表的各个构成如下:

emp(员工信息表)

 dept(部门信息表)

salgrade(薪水等级表)

下面开始我们的练习题:

第一题:取得每个部门最高薪水的人员名称

思路:

SELECT DEPTNO,max(sal)as avgsal FROM `emp`GROUP BY DEPTNO;

先找出每个部门的最高薪水,然后作为临时表与emp连接查询该薪水对应的员工。

答案:

SELECT 
	emp.ENAME,t.* 
FROM 
	emp 
JOIN 
	(SELECT DEPTNO,max(sal)as maxsal FROM `emp`GROUP BY DEPTNO)t 
ON 
	t.DEPTNO = emp.DEPTNO 
and 
	t.maxsal = emp.SAL

 第二题:哪些人薪水在部门的平均薪水之上

思路:

SELECT DEPTNO,avg(sal)as avgsal FROM `emp`GROUP BY DEPTNO

同样先找出每个部门的平均薪资,然后再作为临时表和emp连接查询大于此工资的人

答案:

SELECT 
	emp.ENAME,emp.SAL,t.* 
FROM 
	emp 
JOIN 
	(SELECT DEPTNO,avg(sal)as avgsal FROM `emp`GROUP BY DEPTNO)t 
on 
	t.DEPTNO = emp.DEPTNO 
and 
	emp.SAL>t.avgsal

第三题:取得部门中(所有人的)平均薪水的等级 / 平均的薪水等级

(1)平均薪水的等级

思路:先找出平均薪水再去连接薪水等级表得到等级

答案:

SELECT 
	salgrade.GRADE,t.* 
FROM 
	salgrade 
JOIN 
	(SELECT DEPTNO,avg(sal)as avgsal FROM `emp`GROUP BY DEPTNO)t 
on
	t.avgsal BETWEEN salgrade.LOSAL and salgrade.HISAL

(2)平均的薪水等级

思路:先连接薪水等级的表,然后再算等级的平均值

答案:

SELECT 
	emp.DEPTNO,avg(salgrade.GRADE)as avgGRADE
FROM 
	emp 
JOIN 
	salgrade 
on 
	emp.SAL BETWEEN salgrade.LOSAL and salgrade.HISAL 
GROUP BY emp.DEPTNO

第四题:不用组函数(Max),取得最高薪水

思路:通过排序+limit 1 来获取最值

答案: 

SELECT 
	emp.ENAME,emp.SAL 
FROM 
	emp 
ORDER BY emp.SAL DESC LIMIT 1

第五题:取得平均薪水最高的部门的部门名称

思路:先计算各部门的平均薪水得到临时表,然后和部门信息表连接获取名称,并用max获取最值

答案:

第一种:

SELECT 
	dept.DNAME, max(t.avgsal)as maxavgsal 
FROM 
	dept 
JOIN 
	(SELECT DEPTNO,avg(sal)as avgsal FROM `emp`GROUP BY DEPTNO)t 
on dept.DEPTNO = t.DEPTNO

 第二种:

SELECT 
	dept.DNAME, max(t.avgsal)as maxavgsal 
FROM 
	dept 
JOIN
	(SELECT DEPTNO,avg(sal)as avgsal FROM `emp`GROUP BY DEPTNO ORDER BY avgsal DESC LIMIT 1)t 
on dept.DEPTNO = t.DEPTNO

 【重要】第六题:求平均薪水等级最低的部门的部门名称

思路:先求平均薪水最低的部门,然后用薪水连接薪水等级表对应等级,用部门编号连接部门信息表对应部门名称。

求出最低平均值
SELECT avg(sal)as avgsal FROM `emp`GROUP BY DEPTNO ORDER BY avgsal ASC LIMIT 1

求出最低平均值对应等级
SELECT salgrade.GRADE FROM salgrade JOIN (SELECT avg(sal)as avgsal FROM `emp`GROUP BY DEPTNO ORDER BY avgsal ASC LIMIT 1)r on r.avgsal BETWEEN salgrade.LOSAL and salgrade.HISAL

求出dept和salgrade联合
select dept.DNAME,avg(sal)as avgsal FROM emp JOIN dept on emp.DEPTNO = dept.DEPTNO GROUP BY emp.DEPTNO

答案:

SELECT 
	t.*,salgrade.GRADE 
FROM 
	(select dept.DNAME,avg(sal)as avgsal FROM emp JOIN dept on emp.DEPTNO = dept.DEPTNO GROUP BY emp.DEPTNO)t join 
	salgrade 
on 
	t.avgsal BETWEEN salgrade.LOSAL and salgrade.HISAL 
WHERE 
	GRADE = (SELECT 
		salgrade.GRADE 
	FROM 
		salgrade 
	JOIN 
		(SELECT avg(sal)as avgsal FROM `emp`GROUP BY DEPTNO ORDER BY avgsal ASC LIMIT 1)r 
	on r.avgsal BETWEEN salgrade.LOSAL and salgrade.HISAL)

 第七题:取得比普通员工(员工代码没有在mgr字段上出现的)的最高薪水还要高的领导人姓名

思路:

1、先找出领导人编号MGR

2、然后找出非领导人(普通员工)的最高薪水maxsal

3、然后再整个emp中查找薪水>maxsal且编号属于领导的员工姓名

答案: 

SELECT 
	ENAME 
FROM 
	emp WHERE SAL>(
	SELECT 
		max(SAL)as maxsal 
	FROM 
		emp 
	WHERE EMPNO NOT in(
		SELECT DISTINCT 
			MGR 
		FROM 
			emp 
		WHERE 
			MGR is NOT null)) 
		and 
			EMPNO 
		in (
			SELECT DISTINCT 
				MGR 
			FROM 
				emp 
			WHERE MGR is NOT null)

第八题:取得薪水最高的前五名

SELECT ENAME,SAL FROM emp ORDER BY SAL DESC LIMIT 5

第九题:取得薪水最高的6-10名

SELECT ENAME,SAL FROM emp ORDER BY SAL DESC LIMIT 5,5

第十题:取得最后入职的5名员工

SELECT ENAME,HIREDATE FROM emp ORDER BY HIREDATE DESC LIMIT 5

第十一题:取得每个薪水等级有多少员工

思路:先找出每个薪水对应的等级,然后按照等级分组,并进行count(*)

答案:

SELECT 
	salgrade.GRADE,count(*)
FROM 
	emp 
JOIN 
	salgrade 
WHERE 
	emp.SAL BETWEEN salgrade.LOSAL AND salgrade.HISAL 
GROUP BY 
	salgrade.GRADE

【重要】第十二题:列出所有员工及对应领导的姓名

思路:通过emp表的自连接,a的MGR = b的员工编号得出其领导

答案:

select 
	a.ENAME '员工',b.ENAME '领导' 
from 
	emp a
left JOIN
	emp b
on 
	a.mgr = b.EMPNO

 第十三题:列出受雇日期早于其上级领导的所有员工的编号、姓名、部门名称

思路:在上一题的基础上增加判断条件(a.HIREDATE<b.HIREDATE),并与dept进行连接获取部门名称

答案:

select 
	a.EMPNO '编号',a.ENAME '姓名',a.HIREDATE '雇佣时间',dept.DNAME '部门名称',b.ENAME '领导' ,b.HIREDATE
from 
	emp a
left JOIN
	emp b
on 
	a.mgr = b.EMPNO
JOIN
	dept
on 
	a.DEPTNO = dept.DEPTNO
where 
	a.HIREDATE<b.HIREDATE

第十四题:列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门

SELECT emp.*,dept.* FROM emp JOIN dept on emp.DEPTNO = dept.DEPTNO

第十五题:列出至少有5个员工的所有部门

SELECT DEPTNO FROM emp GROUP BY DEPTNO HAVING count(*) >= 5

第十六题:列出薪水比“SMITH”多的所有员工的信息

答案:

select emp.* FROM emp where sal>(SELECT SAL FROM emp where ENAME = 'SMITH')

第十七题:列出所有“CLERK”(办事员)的姓名及其部门名称、部门的人数

思路:

1、先按照部门分组得出每个部门有多少人

2、与上面临时表连接,并判断JOB = 'CLERK'的员工在那些部门得出所在部门人数

3、与dept连接得到部门的名称

答案:

SELECT 
	emp.ENAME,emp.DEPTNO,dept.DNAME ,t.num as '部门人数'
FROM 
	emp 
JOIN 
	dept 
on 
	emp.DEPTNO = dept.DEPTNO
left JOIN
	(SELECT count(*)as num,emp.DEPTNO from emp GROUP BY DEPTNO)t
ON
	emp.DEPTNO = t.DEPTNO
WHERE 
	JOB = 'CLERK'

第十八题:列出最低薪金大于1500的各种工作及从事此工作的全部雇员人数

思路:

1、按照工作分组,求出各个工作的最低薪水

2、然后用emp与上面临时表相连,求出薪水大于最低薪水的人的信息,并进行count

或者直接按工作分组,求出最低薪水对应的工作,然后直接计算count,将条件放到having中。

答案: 

select 
	count(*)as num,JOB 
FROM 
	emp 
GROUP BY 
	job 
HAVING JOB in (SELECT JOB from emp GROUP BY JOB HAVING min(SAL)>1500)

第十九题:列出在部门“SALES”<销售部>工作的员工的姓名,假定不知道销售部的部门编号

答案:

SELECT 
	ENAME 
FROM 
	emp 
WHERE DEPTNO = (SELECT DEPTNO FROM dept WHERE DNAME = "SALES")

 【重要】第二十题:列出薪金高于公司平均薪金的所有员工,所在部门、上级领导、雇员的工资的等级

思路:

1、先求出平均薪水

2、然后就是,工资等级需要连接薪水等级表、所在部门需要连接dept

答案:

SELECT
	emp.ENAME,dept.DNAME,l.ENAME,salgrade.GRADE
from
	emp
JOIN
	dept
ON
	dept.DEPTNO =emp.DEPTNO
LEFt JOIN
  emp l
ON
	emp.MGR = l.EMPNO
JOIN
	salgrade
ON
	emp.SAL BETWEEN salgrade.LOSAL AND salgrade.HISAL
WHERE
	emp.SAL>(SELECT avg(SAL) from emp)

 第二十一题:列出与“SCOTT”从事相同工作的所有员工及部门名称

思路:找出SCOTT从事的工作。然后连接dept表接口

答案:

SELECT 
	ENAME,JOB,dept.DNAME 
FROM 
	emp 
JOIN 
	dept 
ON 
	emp.DEPTNO = dept.DEPTNO 
WHERE 
	JOB = (SELECT JOB FROM emp WHERE ENAME = "SCOTT")

第二十二题:列出薪金等于部门30中员工的薪金的其他员工的姓名和薪金

答案:

SELECT ENAME,SAL FROM emp WHERE SAL in (SELECT DISTINCT SAL FROM emp WHERE DEPTNO = 30) AND DEPTNO < 30 

第二十三题:列出薪金高于部门30工作的所有员工的薪金的员工姓名和薪金,部门名称

思路:

1、先找出部门30中的最高薪水

2、连接dept获取部门名称即可

答案:

SELECT 
	ENAME,SAL,dept.DNAME 
FROM 
	emp 
JOIN 
	dept 
on 
	dept.DEPTNO = emp.DEPTNO 
WHERE 
	SAL > (SELECT max(SAL) FROM emp WHERE DEPTNO = 30)

第二十四题:列出在每个部门工作的员工数量,平均工资和平均服务期限

思路:按照部门分组,注意日期的处理函数

答案: 

SELECT 
	dept.DEPTNO,count(ENAME),IFNULL(avg(SAL),0) ,avg(TIMESTAMPDIFF(YEAR,HIREDATE,NOW()))
FROM 
	emp 
right JOIN 
	dept 
on 
	emp.DEPTNO = dept.DEPTNO 
GROUP BY 
	dept.DEPTNO

【注意】MySQL中对应日期计算的函数

Mysql中对于日期的计算的函数 间隔类型可以是 
YEAR 年
QUARTER 季度
MONTH 月
WEEK 周
DAY 日
HOUR 小时
MINUTE 分钟
SECOND 秒

SELECT TIMESTAMPDIFF(YEAR,HIREDATE,NOW()) FROM emp

第二十五题:列出所有员工的姓名、部门名称、工资

思路:

答案:

SELECT 
    e.ENAME,d.DNAME,e.SAL
FROM 
    emp e
LEFT JOIN 
    dept d
on 
    e.DEPTNO = d.DEPTNO

 第二十六题:列出所有部门的详情信息和人数

答案:

SELECT dept.* ,count(ENAME) FROM emp right JOIN dept on emp.DEPTNO = dept.DEPTNO GROUP BY DEPTNO

 第二十七题:列出各种工作的最低工资及从事此工作的雇员姓名

思路:

1、按照工作分组,得出各工作的最低薪水及工作

2、emp和临时表连接,判断条件为工作相同,薪水相同,从而得出雇员姓名

答案:

SELECT 
	emp.ENAME,t.* 
FROM 
	emp 
JOIN 
	(SELECT MIN(sal)as MINSAL,JOB from emp GROUP BY JOB)t 
on 
	emp.JOB = t.JOB AND emp.SAL = t.MINSAL

 第二十八题:列出各个部门的MANAGER(领导)的最低薪金

思路:

1、与dept连接找出各个部门的MGR(因为有些部门可能没有人员,所以连接dept更精确)

2、按照部门分组,且工作等于MANAGER的人,求min(sal)

答案:

SELECT 
	min(SAL) ,t.MGR,t.DEPTNO 
FROM 
	emp 
right JOIN 
	(SELECT MGR,emp.DEPTNO FROM emp RIGHT JOIN dept ON emp.DEPTNO = dept.DEPTNO )t 
on 
	t.DEPTNO = emp.DEPTNO  
WHERE 
	JOB = "MANAGER" 
GROUP BY 
	t.DEPTNO

 第二十九题:列出所有员工的年工资,按年薪从低到高排序

SELECT ENAME,(SAL+IFNULL(COMM,0))*12 as YEARSsal FROM emp ORDER BY YEARSsal ASC

第三十题:求出员工领导薪水超过3000的员工名称与领导名称

思路:直接自连接,领导薪水>3000

答案:

//第一种
SELECT 
	emp.ENAME '员工名称', t.ENAME '领导名称' 
FROM 
	emp 
JOIN 
	(SELECT a.EMPNO,a.ENAME FROM emp a left JOIN emp b on a.MGR = b.EMPNO WHERE a.SAL>3000)t 
ON 
	t.EMPNO = emp.MGR

//第二种(自连接写法)
SELECT 
	a.ENAME'员工名称',b.ENAME'领导名称' 
FROM 
	emp a 
JOIN 
	emp b 
ON 
	a.MGR = b.EMPNO 
WHERE b.SAL > 3000

第三十一题:求出部门名称中,带'S'字符的部门员工的工资合计、部门人数

思路:按部门分组,与dept连接,判断DNAME like "%S%"

答案:

SELECT 
	dept.*,count(emp.ENAME),ifnull(sum(emp.SAL),0)
FROM 
	emp 
right join 
	dept 
ON 
	emp.DEPTNO = dept.DEPTNO 
WHERE
	dept.DNAME LIKE "%S%"
GROUP BY 
	dept.DEPTNO

第三十二题: 给任职日期超过30年的员工加薪10%

UPDATE emp SET SAL = SAL*1.1 WHERE (TIMESTAMPDIFF(YEAR,HIREDATE,NOW()))>30

力扣SQL题解

178.分数排名

 

编写 SQL 查询对分数进行排序。排名按以下规则计算:

  • 分数应按从高到低排列。
  • 如果两个分数相等,那么两个分数的排名应该相同。
  • 在排名相同的分数后,排名数应该是下一个连续的整数。换句话说,排名之间不应该有空缺的数字。

按 score 降序返回结果表。

查询结果格式如下所示。

 结题思路:首先创建这张表

Create table If Not Exists Scores (id int, score DECIMAL(3,2))

insert into Scores (id, score) values ('1', '3.5')
insert into Scores (id, score) values ('2', '3.65')
insert into Scores (id, score) values ('3', '4.0')
insert into Scores (id, score) values ('4', '3.85')
insert into Scores (id, score) values ('5', '4.0')
insert into Scores (id, score) values ('6', '3.65')

这个题这样梳理一下可能更容易理解:

最后的结果包含两个部分,第一部分是降序排列的分数,第二部分是每个分数对应的排名。

第一部分不难写:

select a.Score as Score
from Scores a
order by a.Score DESC

比较难的是第二部分,假设现在有一个分数X,如何算出它的排名Rank呢?我们可以先提取出大于等于X的所有分数集合H,将H去重后的元素个数就是X的排名。可以按一下理解

select b.Score from Scores b where b.Score >= X;

我们要的是集合H去重之后的元素个数,因此变为如下所示:

select count(distinct b.Score) from Scores b where b.Score >= X as Rank;

那此时的X在题目中是什么,就是对应到第一部分的分数,所以这里的C就是a.Score,将两个部分结合起来为:

select a.Score as Score,
(select count(distinct b.Score) from Scores b where b.Score >= a.Score) as Rank
from Scores a
order by a.Score DESC

180.连续出现的数字

编写一个 SQL 查询,查找所有至少连续出现三次的数字。

返回的结果表中的数据可以按 任意顺序 排列。

查询结果格式如下面的例子所示:

解题思路:

首先这道题看起来很简单,但是比较复杂的一个点是连续出现三次,所以我们需要处理这个问题,我们通过多表连接即可实现。代码如下:

SELECT DISTINCT
    l1.Num AS ConsecutiveNums
FROM
    Logs l1,
    Logs l2,
    Logs l3
WHERE
    l1.Id = l2.Id - 1
    AND l2.Id = l3.Id - 1
    AND l1.Num = l2.Num
    AND l2.Num = l3.Num

182:查找重复的电子邮箱 

 这个题目很简单,我们可以用having子句,having子句和where的区别是having子句是用在group by后面的条件语句。

答案:

select Email
from Person
group by Email
having count(Email) > 1;

184:部门工资最高的员工

 

首先,我们看到题目很简单的会直接连接两表分组求最值

select Department.name as Department,Employee.name as Employee,max(Employee.salary) as salary
from Employee left join Department on Employee.departmentId = Department.id
group by Department

得到的结果是:

但是在此题中,我们要注意的是每个部门最高工资的不仅只有一个人。所有我们不能直接两表连接,分组求最值,这样得出的结果每个部门只会有一个人,不符合题意。我们应该先求出每个部门的最高工资是多少,然后再连接用IN得出有哪些人是该工资。

SELECT
    DepartmentId, MAX(Salary)
FROM
    Employee
GROUP BY DepartmentId;
SELECT
    Department.name AS 'Department',
    Employee.name AS 'Employee',
    Salary
FROM
    Employee
        JOIN
    Department ON Employee.DepartmentId = Department.Id
WHERE
    (Employee.DepartmentId , Salary) IN
    (   SELECT
            DepartmentId, MAX(Salary)
        FROM
            Employee
        GROUP BY DepartmentId
	)

 185:部门工资前三高的所有员工

公司的主管们感兴趣的是公司每个部门中谁赚的钱最多。一个部门的 高收入者 是指一个员工的工资在该部门的 不同 工资中 排名前三 。

编写一个SQL查询,找出每个部门中 收入高的员工 。

 

答案: 此题首先需要得出的是每个部门前三高的工资,然后再连接部门表,一般我们找的是每个部门的最高薪资或者最低薪资,可以通过GroupBy和MAX、MIN函数求出,但这种求出前几的情况不是很好处理,下面我们介绍几种窗口函数(很重要)

常用窗口函数总结:

  1. row_number() over(partition by字段1 order by 字段2) 的结果是每一行记录生成一个序号,依次排序且排序的序号不会重复
  2. rank() over(partition by字段1 order by 字段2) 的结果会考虑排序字段值相同的情况,若排序字段的值相同则其序号是一样的,后续不同字段值的序号为(前一行序号+N,其中N为前一个字段值重复的行数),比如 1 1 3 4 4 4 7
  3. dense_rank() over(partition by字段1 order by 字段2) 的结果也会考虑排序字段值相同的情况,即排序字段的值相同那么他们的序号是一样的,但是与rank() 的区别是后续不同字段值的序号为(前一行序号+1),比如 1 1 2 2 3 4 5

代码:

SELECT 
    d.Name  Department,
    e.Name  Employee,
    e.Salary
FROM (
    SELECT 
        DENSE_RANK() OVER (partition by DepartmentId order by Salary desc) AS ranking, 
        DepartmentId, Name, Salary
    FROM employee
) e
LEFT JOIN department d ON e.DepartmentId=d.id
WHERE e.ranking <= 3;

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智博的自留地

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值