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
select
id, month,
sum(salary) over(partition by id
order by month desc
range between 0 preceding and2 following
) salary
from employee where (id, month) not in (
select id, max(month) month from employee group by id
);
select
id, month,
sum(salary) over(partition by id
order by month
range 2 preceding
) salary
from employee where (id, month) not in (
select id, max(month) month from employee group by id
)
order by id, month desc;
select
id, month,
sum(salary) over(partition by id order by month range 2 preceding) salary
from (
select
id, month, salary,
row_number() over(partition by id order by month desc) rk
from employee
) e1 where rk >=2order by id, month desc;
解析
这三种写法都是一样的,上面两种是通过 not in 的方式去除掉当前最大月份,第三种是通过使用 row_number() 窗口函数去掉最大月份。
SQL:方法三
selecte1.id id, e1.month month,
sum(e2.salary) salary
from employee e1, employee e2
wheree1.id=e2.idande1.month>=e2.monthande1.month<e2.month+3and (e1.id, e1.month) not in (
select id, max(month) month from employee group by id
)
group bye1.id, e1.monthorder bye1.id, e1.monthdesc;
题目
编写 SQL 语句,对于每个员工,查询他除最近一个月(即最大月)之外,剩下每个月的近三个月的累计薪水(不足三个月也要计算)。
结果请按
id
升序,然后按month
降序显示。SQL:方法一
解析
因为要累计计算最近三个月的薪资,所以就要连续自连三次,自连的条件是
id
和month - 1
和month - 2
这里如果使用
e2.month - 1 = e1.month
和e3.month - 2 = e1.month
会有问题,因为我们这里最后会计算e1.salary + e2.salary + e3.salary
。这里以
id = 1
举例:这是
e2.month = e1.month - 1
和e3.month = e1.month - 2
的结果这是
e2.month - 1 = e1.month
和e3.month - 2 = e1.month
的结果使用
e2.month - 1 = e1.month
的问题是,e2
表的第二行不是2
月份的数据,而是4
月份的数据。找出每个
id
最大的月份,存储为临时表e4
将第一步的结果使用
join
连接e4
,筛选条件id
和e1.month < e4.max_month
这里为什么使用
left join
而不是使用join
,因为要去除掉最大月份,使用e1.month < e4.max_month
时会有一条数据是null
,使用join
能够去除掉这条数据。使用
ifnull
判断是否每张表的salary
是否为null
,并且相加,就是每个月薪资累加的和。Tips
有个问题,如果月份不连续,比如下面的数据
7月
和4月
不连续,使用这个方法计算7月
的累计薪资是7月
、6月
、5月
,不会计算到4月
的薪资。SQL:方法二
解析
这三种写法都是一样的,上面两种是通过
not in
的方式去除掉当前最大月份,第三种是通过使用row_number()
窗口函数去掉最大月份。SQL:方法三
两表查询
employee e1, employee e2
查询条件
e1.id = e2.id
这好理解,e1.month >= e2.month and e1.month < e2.month + 3
怎么理解呢,最近三个月就加 3 吗?这就要配合sum(e2.salary)
来理解了我们先看第一个筛选条件
e1.id = e2.id
,只需要两个相同id
的数据从输出结果可以看出
e1.id = 1, e1.month = 4
的salary
是由group_concat(e2.salary)
的 4 个数相加,这 4 个值是e2.id = 1, e2.month = 4,3,2,1
的salary
。增加筛选条件
e1.month >= e2.month
,累加当前月份的salary
和之前所有所有月份的salary
从结果中可以看出
e1.id = 1, e1.month = 2
的salary
由group_concat(e2.salary)
的 2 个数相加,这两个值是有e2.id = 1, e2.month = 2,1
的salary
。增加筛选提条件
e1.month < e2.month + 3
,只累加当前月份以及前 2 个月的salary
,这一步再加个group_concat(e2.month)
,帮助我们更好理解。加
e1.month < e2.month + 3
,group_concat(e2.month)
的结果加了
e1.month < e2.month + 3
,group_concat(e2.month)
的结果通过第二步筛选,得到所有的数据
e1.month
一定大于等于e2.month
,因为要的结果是最近三个月的salary
累加,所以上面一张图中的1,4,2,3
是不符合要求的。如何把这些月份过滤掉用的就是e1.month < e2.month + 3
,比如当前月份是8
月份,那个最近的 3 个月是8,7,6
,8<8+3, 8<7+3, 8<6+3
。去除最大月份,分组查询一次就能得到。
The text was updated successfully, but these errors were encountered: