pivot行转列实践:仿工资查询

今天带来的是pivot行转列的一个案例,根据工资查询抽象来的

首先是理解查询工资的表结构
1、首先工资是我们的工资,所以要有一个一个表
2、工资有许多部分组成,所以要有项目表
3、由上边两表即可再组合出新表项目工资表(一个人可以有多个工资项目)
4、最后就是工资表

既然表已经确定,接下来就是建表了

① --员工表(员工ID、工号、姓名、性别)


SELECT * INTO 
#Employee 
FROM (
	SELECT 1 ID,100001 WorkCode,'张三' [Name],0 sex
	UNION
	SELECT 2,100002,'李四' ,0
	UNION
	SELECT 3,100003,'王五' ,0
	UNION
	SELECT 4,100004,'小明' ,0
	UNION
	SELECT 5,100005,'小红' ,1
	UNION
	SELECT 6,100006,'李华' ,1
	) a

② --工资项目表(ID、名称)
–有社会工作经验的都知道,我们工资是有多部门组成的并不是单一的,也不是一层不变的,好比基本工资,这是不管如何都要发的,还有岗位工资,你是在这个岗位上的工资,
–公司有福利等,有餐补,住房补贴等,我们也有五险一金要交(虽然不是给公司,但是得从工资里扣)(刚踏足社会找工作的朋友记得留心,这是公司必须要给我们办理的,没有的话可以举报,…(苦口婆心800字省略))

SELECT * INTO 
#SalaryElement
FROM (
	SELECT 1 SalaryElementID,'基本工资' [SalaryItemName]
	UNION
	SELECT 2,'岗位工资' 
	UNION
	SELECT 3,'餐补补贴' 
	UNION
	SELECT 4,'宿舍费用' 
	UNION
	SELECT 5,'固定绩效' 
	UNION
	SELECT 6,'考核绩效' 
	UNION
	SELECT 7,'平时加班' 
	UNION
	SELECT 8,'周末加班' 
	UNION
	SELECT 9,'五险一金'
	UNION
	SELECT 10,'其他类别'
	) a

③ --项目工资表(ID、员工ID、项目ID、工资金额、工资表ID(表④的))
其实这里就已经算是可以查工资明细了,但是还有别的原因不能在这里查
讲解一条数据:员工ID为1的员工在工资项目为1的工资为1000元,他的工资表ID为1
这里SQL较长,但是数据有规律,有想法的小伙伴可以自己写个方法的出同样的效果

SELECT * INTO 
#SalaryItem
FROM (
	SELECT 1 ID,1 EmpID, 1 ElementID,1000 [Money],1 SalaryID
	UNION
	SELECT 2,1,2,1000,1 UNION
	SELECT 3,1,3,1000,1 UNION
	SELECT 4,1,4,1000,1 UNION
	SELECT 5,1,5,1000,1 UNION
	SELECT 6,1,6,1000,1 UNION
	SELECT 7,1,7,1000,1 UNION
	SELECT 8,1,8,1000,1 UNION
	SELECT 9,1,9,1000,1 UNION
	SELECT 10,1,10,1000,1 UNION
	--李四
	SELECT 11,2,1,2000,2 UNION	 	  
	SELECT 12,2,2,2000,2 UNION	 	  
	SELECT 13,2,3,2000,2 UNION		  
	SELECT 14,2,4,2000,2 UNION	 	  
	SELECT 15,2,5,2000,2 UNION		  
	SELECT 16,2,6,2000,2 UNION	 	  
	SELECT 17,2,7,2000,2 UNION	 	 
	SELECT 18,2,8,2000,2 UNION	  	  
	SELECT 19,2,9,2000,2 UNION
	SELECT 20,2,10,2000,2 UNION
	--王五
	SELECT 11,3,1,3000,3 UNION	 	  
	SELECT 22,3,2,3000,3 UNION	 	  
	SELECT 23,3,3,3000,3 UNION		  
	SELECT 24,3,4,3000,3 UNION	 	  
	SELECT 25,3,5,3000,3 UNION		  
	SELECT 26,3,6,3000,3 UNION	 	  
	SELECT 27,3,7,3000,3 UNION	 	 
	SELECT 28,3,8,3000,3 UNION	  	  
	SELECT 29,3,9,3000,3 UNION
	SELECT 30,3,10,3000,3 UNION
	--小明
	SELECT 31,4,1,4000,4 UNION	 	  
	SELECT 32,4,2,4000,4 UNION	 	  
	SELECT 33,4,3,4000,4 UNION		  
	SELECT 34,4,4,4000,4 UNION	 	  
	SELECT 35,4,5,4000,4 UNION		  
	SELECT 36,4,6,4000,4 UNION	 	  
	SELECT 37,4,7,4000,4 UNION	 	 
	SELECT 38,4,8,4000,4 UNION	  	  
	SELECT 39,4,9,4000,4 UNION
	SELECT 40,4,10,4000,4 UNION
	--小红
	SELECT 41,5,1,5000,5 UNION	 	  
	SELECT 42,5,2,5000,5 UNION	 	  
	SELECT 43,5,3,5000,5 UNION		  
	SELECT 44,5,4,5000,5 UNION	 	  
	SELECT 45,5,5,5000,5 UNION		  
	SELECT 46,5,6,5000,5 UNION	 	  
	SELECT 47,5,7,5000,5 UNION	 	 
	SELECT 48,5,8,5000,5 UNION	  	  
	SELECT 49,5,9,5000,5 UNION
	SELECT 50,5,10,5000,5 UNION
	--李华
	SELECT 51,6,1,6000,6 UNION	 	  
	SELECT 52,6,2,6000,6 UNION	 	  
	SELECT 53,6,3,6000,6 UNION		  
	SELECT 54,6,4,6000,6 UNION	 	  
	SELECT 55,6,5,6000,6 UNION		  
	SELECT 56,6,6,6000,6 UNION	 	  
	SELECT 57,6,7,6000,6 UNION	 	 
	SELECT 58,6,8,6000,6 UNION	  	  
	SELECT 59,6,9,6000,6 UNION
	SELECT 60,6,10,6000,6 
	) a

④–工资表(ID、员工ID、年月)
上边表③说了,那里就可以查询了,但是需要表④,也就是年月的原因,那把年月加到表③不就行了么?是这样么,真正工资表数据并不是我这里这么简单还有其他字段,我只是抽出主要的

	SELECT * INTO 
#Salary
FROM (
	SELECT 1 ID,1 EmpID,'2020-07' Years 
	UNION
	SELECT 2,2,'2020-07' 
	UNION
	SELECT 3,3,'2020-07' 
	UNION
	SELECT 4,4,'2020-07' 
	UNION
	SELECT 5,5,'2020-07' 
	UNION
	SELECT 6,6,'2020-07' 
	)a

  • 现在表已经建好并添加了测试数据了,那就进行真经事了
  • 关联数据表
select  *
from #Salary x
left join #Employee e on e.ID =x.EmpID
left join #SalaryItem Item on Item.SalaryID =x.ID
left join #SalaryElement element on element.SalaryElementID = Item.ElementID

查询结果呢就是下图了
在这里插入图片描述
这里我们可以清楚的看到一个人对各项目的金额

--现在的数据还是以每个工资项目为一列显示的,对于我们的工资条来说,这还不是最后的结果
--那现在我们要做的就是列转行
--使用pivot for
--先列出我们要查的工资项

这里为了代码的美观,我使用参数进行处理查询的列


declare @ItemPivot nvarchar(max)
declare @ItemPivotShow nvarchar(max)

set @ItemPivot = ''--pivot内对接的
set @ItemPivotShow = '' --最终显示的


SET @ItemPivot='
[基本工资],[岗位工资],[餐补补贴],[宿舍费用],[考核绩效],
[固定绩效],[平时加班],[周末加班],[五险一金],[其他类别]
';
SET @ItemPivotShow='
isnull([基本工资],0) [基本工资],
isnull([岗位工资],0) [岗位工资],
isnull([餐补补贴],0) [餐补补贴],
isnull([宿舍费用],0) [宿舍费用],
isnull([考核绩效]+[固定绩效],0) [绩效],
isnull([平时加班]+[周末加班],0) [加班],
isnull([五险一金],0) [五险一金],
isnull([其他类别],0) [其他]
,isnull([基本工资] + [岗位工资] + [餐补补贴] + [宿舍费用] + [考核绩效] + [固定绩效] + [平时加班] + [周末加班] - [五险一金] - [其他类别],0) [应发金额]
--,isnull([基本工资] + [岗位工资] + [餐补补贴] + [宿舍费用] + [考核绩效] + [固定绩效] + [平时加班] + [周末加班] - [五险一金] - [其他类别],0) [实发金额]

然后呢,就是筛选条件了(像我们查一个人的工资,某个月的工资)

declare @years nvarchar(max) --这个可做存储过程的参数用
set @years ='2020-07'
--还可加姓名、工号等(只限制于这里)

declare @pWhere nvarchar(max)
set @pWhere = ''
set @pWhere = 'x.Years=''' + @years + ''''

最后就到主角pivot登场了

declare @SalaryShow nvarchar(max)
set @SalaryShow = '
select ID,Years,WorkCode,Name, ' + @ItemPivotShow + ' 
from (
	select  x.ID,x.Years,e.WorkCode,e.Name,Money,SalaryItemName
    from #Salary x
    left join #Employee e on e.ID =x.EmpID
    left join #SalaryItem Item on Item.SalaryID =x.ID
    left join #SalaryElement element on element.SalaryElementID = Item.ElementID
	where ' + @pWhere + '
) t pivot (max(Money) for SalaryItemName in (' + @ItemPivot + ')) s
'
--pivot 聚合函数(int等类型的字段) for 要显示的列的字段 in (需要用的字段)

最后就是执行了


EXEC (@SalaryShow
+'
DROP TABLE #Employee
DROP TABLE #SalaryElement
DROP TABLE #SalaryItem
DROP TABLE #Salary
'
)

最后:关于对这类的讲解、优化及拓展

  1. 对于上边添加临时表的SQL,大家可以把他存入字段中,类似这里的@SalaryShow参数一样,然后再最后的EXEC内相加与@SalaryShow之前即可
  2. 因为我们需要缴税,所以上边的应发工资还不一定是实际我们到手的工资,所以,我们还可以加个扣税处理,进行扣税管理,得出实发工资(后边有空我再看下吧…)
  3. 我们建立SalaryItem表是因为要可维护的原因,所以单独做了一个表,工资的组成有很多,不同地方也有不同的工资项目,好比宿舍费用,有的公司不提供宿舍,也没有宿舍补贴之类的
  4. 实际上的工资计算是没有我这里所描述的这么简单,因为没一个工资项的工资已经得出来了,在实际中,我们要多方面取值
    (像考勤,有迟到早退的,加班得申请并通过才有效,加班了有与打卡考勤有关,是否是有效加班呢,加班工资又安什么规则计算呢,不同公司不同部门又不一样,还有考核…)
    …(再次省略不知道多少字,半瓶水,也不能全理解工资方面的,我只是一个菜鸟码农)
  5. 这段SQL也可以做成存储过程,参数可以是年月、工号、姓名,有意拓展的话可以再把员工表分细点,加上公司部门岗位,然后查

这就是pivot行转列实践:真实工资查询的全部内容了。谢谢阅读!

追加:https://download.csdn.net/download/qq_44471040/12674013
这是我整理上传上去的的SQL脚本,有能力的小伙伴可以下载支持下!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值