MS SQL 竟然被一个分组求和的问题卡了半天

最近有个人员考勤的项目,要判断员工请病假是否超出了医疗期, 本以为很简单的需求,却频频出错
情况如下:
首先每个员工根据资历不同,有不同的医疗期 ,这个医疗期呢每个员工还有不同的计算周期,比如A员工在12个月内病假超过3个月就算超出医疗期,B员工在15个月内病假超过4个月就算超出医疗期.
数据库里的人员资料里已经根据资历等条件计算出了病假的计算周期和医疗期。也有一张表存储着每个月的病假天数。

表1 基础资料表 A01

  •         人员ID   姓名   医疗期  计算周期 
    
  •        nameid   name     ylq    jszq
    
  •         101     张三      3      4
    
  •         102     李四      2      5
    
  •         103     王五      4      6
    

首先和客户确认的是医疗期按照30天来计算月,就是张三在4个月内病假天数不超过90天就算不超医疗期,不考虑大小月

表2 病假表 B01

  • 人员ID      姓名     病假天数    期间
    
  • nameid     name     bjts       YYMM
    
  • 101        张三       31       202301
    
  • 101        张三       28       202302
    
  • 101        张三       31       202303
    
  • 101        张三       30       202304
    
  • 101        张三       0        202305
    
  • 101        张三       0        202306
    
  • 102        李四       31       202301
    
  • 102        李四       28       202302
    
  • 102        李四       31       202303
    
  • 102        李四       25       202304
    
  • 102        李四       0        202305
    
  • 102        李四       0        202306
    
  • 103        王五       0        202301
    
  • 103        王五       15       202302
    
  • 103        王五       31       202303
    
  • 103        王五       30       202304
    
  • 103        王五       31       202305
    
  • 103        王五       30       202306
    

乍一看,我的第一反应就是 用TOP (计算周期) 来解决,每个人取 TOP计算周期里的病假合计, 大于医疗期就算超出了。

点击查看代码

  select nameid,SUM(bjts) AS BJHJ
 from 
 (
  select TOP (select  jszq from a01 where nameid=001) b01.yymm,b01.nameid,b01.bjts 
 from b01
 where b01.nameid=001
  ORDER BY b01.payym DESC
 ) topbj
 group by nameid

结果也很喜人

  • nameid  	BJHJ
    
  • 101	          61
    

这样结果和医疗期*30判断一下大小就可以了
然后尝试直接查所有数据 ,将以上语句中限制人员ID的去掉
结果报错,子查询返回的值不止一个,这个时候,我魔障了似的寻求TOP语句怎么解决这个问题,花费我半天时间。
最终确认是思路不太对啊,TOP不知道怎么按人分组(主要是我不会),我需要每个人的前N条。
重新整理思路,使用row_number ()

select 
	nameid ,name ,bjts,yymm,jszq
from		
	(select  
		row_number () over (partition by t.nameid order by t.yymm desc) rn , *
			from 
				(select a01.jszq,b01.*
					from a01,b01 
						where a01.nameid=b01.nameid
				) t
				
	) tt
where rn <=jszq
order by nameid desc

输出结果

  •   nameid	name	bjts	yymm	jszq
    
  •   103	    王五  	30	202306	6
    
  •   103	    王五  	31	202305	6
    
  •   103	    王五  	30	202304	6
    
  •   103	    王五  	31	202303	6
    
  •   103	    王五  	15	202302	6
    
  •   103	    王五  	0	202301	6
    
  •   102	    李四  	0	202306	5
    
  •   102	    李四  	0	202305	5
    
  •   102	    李四  	25	202304	5
    
  •   102	    李四  	31	202303	5
    
  •   102	    李四  	28	202302	5
    
  •   101	    张三  	0	202306	4
    
  •   101	    张三  	0	202305	4
    
  •   101	    张三  	30	202304	4
    
  •   101	    张三  	31	202303	4
    

至此,思路顺畅,然后前面再嵌套一些求和和比较大小的语句就不赘述了

总结 ,不能被下意识的反应左右,从多个角度考虑问题

posted @ 2024-07-29 18:22  糖果13  阅读(37)  评论(0)    收藏  举报