You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
createtableemployee (
id intprimary key auto_increment,
name varchar(255),
salary int,
departmentId int
);
createtabledepartment (
id intprimary key auto_increment,
name varchar(255)
);
insert into employee (name, salary, departmentId) values
('joe', 85000, 1),
('henry', 80000, 2),
('sam', 60000, 2),
('max', 90000, 1),
('janet', 69000, 1),
('randy', 85000, 1),
('will', 70000, 1);
insert into department(name) values('it'),('sales');
SQL
selectdepartment.id, employee.name, employee.salaryfrom (
selectte.departmentId, te.salary,
case ①
when @pre=departmentId then @rank:=@rank +1
when @pre:=departmentId then @rank:=1
end as 排名
from (select @pre:=null, @rank:=0) tt,
(
select departmentId, salary from employee
group by departmentId, salary
order by departmentId, salary desc
) te
) t
inner join department ont.departmentId=department.idinner join employee ont.departmentId=employee.departmentIdandemployee.salary=t.salaryand 排名 <=3order byt.departmentId, t.salarydesc;
解析
将 employee 按照 departmentId 和 salary 进行分组,将这个临时表命名为 te
使用 case ... when ... then ... end 和变量根据薪水算出排名,将这个临时表命名为 t。
使用两次 inner join 分别连接 department 和 employee
t 表和 department 表连接条件是 t.departmentId = department.id
t 表和 employee 表连接条件是 t.departmentId = employee.departmentId and t.salary = employee.salary ②
Tips:
① case 语句中 when 应该是条件,这里为什么用赋值 :=
查询第一条数据进入 case 时, when @prev = departmentId then ... 执行的时,此时 @prev 为 null 不满足条件,所以它就会执行 when @prev := departmentId then ... ,此时 @prev 为第一条数据的 departmentId 由于赋值语句肯定为 true ,所以 @rank 就为 1
查询第二条数据进入 case 时, when @prev = departmentId then ... 由于 @prev 有值了,下面的 when 就不会执行了。
查询第三条数据进入 case 时, when @prev = departmentId then ... ,第三条数据的 departmentId 是一个新的值,此时不满足 @prev = departmentId ,就会进入第二个 when @prev := departmentId then ... 将 departmentId 的最新值赋值给 @prev
按照上面步骤直到所有的数据都查询完。
② 这里为什么用 t.salary = employee.salary 而不用 t.name = employee.name
t.salary = employee.salary 作用是确定是同一个用,这里就有个问题,确定同一个人的话,为什么不用 name 做条件呢? 这里是因为 te 按照 salary 和 department 进行分组,不考虑 name 的原因是可能会有两个人的 salary 是一样的,如果在加上 name 的话,就会出现两个 salary 相同的人,排名不一样。
题目
找出每个部门获得前三高工资的所有员工
SQL
解析
employee
按照departmentId
和salary
进行分组,将这个临时表命名为te
case ... when ... then ... end
和变量根据薪水算出排名,将这个临时表命名为t
。inner join
分别连接department
和employee
t
表和department
表连接条件是t.departmentId = department.id
t
表和employee
表连接条件是t.departmentId = employee.departmentId and t.salary = employee.salary
②Tips:
①
case
语句中when
应该是条件,这里为什么用赋值:=
case
时,when @prev = departmentId then ...
执行的时,此时@prev
为null
不满足条件,所以它就会执行when @prev := departmentId then ...
,此时@prev
为第一条数据的departmentId
由于赋值语句肯定为true
,所以@rank
就为1
case
时,when @prev = departmentId then ...
由于@prev
有值了,下面的when
就不会执行了。case
时,when @prev = departmentId then ...
,第三条数据的departmentId
是一个新的值,此时不满足@prev = departmentId
,就会进入第二个when @prev := departmentId then ...
将departmentId
的最新值赋值给@prev
② 这里为什么用
t.salary = employee.salary
而不用t.name = employee.name
t.salary = employee.salary
作用是确定是同一个用,这里就有个问题,确定同一个人的话,为什么不用name
做条件呢? 这里是因为te
按照salary
和department
进行分组,不考虑name
的原因是可能会有两个人的salary
是一样的,如果在加上name
的话,就会出现两个salary
相同的人,排名不一样。现在给的数据有两个人的
salary
是一样的,可以将其中一个salary
修改一下,就可以知道结果了。The text was updated successfully, but these errors were encountered: