目的:

工资系统中,在计算各工资项目的时候,用户能自定义公式。这里的讲述是从数据库方设计方面考虑,做简要的数据模拟和实体、存储过程的设计。

收集数据:

1.Employee员工信息数据(EmployeeID,Name,Sex,Department,Position,Joindate(到职日期),DimissionDate(离职日期)… …)

2.Salay员工工资清单(SalaryMonth(工资月份),Employee(员工),基本工资,岗位津贴,技术津贴,住宿费,上月余额,应得工资,本月余额,实得工资 … …)

分析:

这里只是作为Demo,就制作一个简单的数据分析。

1.Employee员工信息就认为一个对象实体,不做详细的数据提取筛分。

2.在Salay员工工资清单,可以把“基本工资,岗位津贴,技术津贴,住宿费 。。。”这些项提取出来,归类为SalaryItem工资项目;SalaryItem工资项目还可以再分类为“公式项”与“非公式项”。(注:“公式项”是指可以使用公式来计算非手工输入的工资项目)当然还可以根据实际的需要分类的更详细,清晰。

数据表:

根据上面的简单分析,可以设计出作Demo使用的表,

1.Emplyee:员工信息表。

2.Salary:员工工资表

3.SalaryItem:工资项目表

4.Formulary:公式表

5.SysSalaryItemTypeMTR:工资项目分类表

建表:


USE [test]GO/*建表脚本*/If object_id('Salary') Is Not Null Drop Table SalaryIf object_id('Formulary') Is Not Null Drop Table FormularyIf object_id('Employee') Is Not Null Drop Table EmployeeIf object_id('SalaryItem') Is Not Null Drop Table SalaryItemIf object_id('SysSalaryItemTypeMTR') Is Not Null Drop Table SysSalaryItemTypeMTRGoCREATE TABLE [SysSalaryItemTypeMTR](    [ID] [smallint] IDENTITY(1,1) NOT NULL,    [Name] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,CONSTRAINT [PK_SysSalaryItemTypeMTR] PRIMARY KEY CLUSTERED(    [ID] ASC))CREATE TABLE [Employee](    [ID] [int] IDENTITY(1,1) NOT NULL,    [EmployeeNo] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,    [Name] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,    [Sex] [nchar](1) COLLATE Chinese_PRC_CI_AS NOT NULL,    [Department] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,    [Position] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,    [JoinDate] [datetime] NULL,    [DimissionDate] [datetime] NULL,CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED(    [ID] ASC))CREATE TABLE [SalaryItem](    [ID] [smallint] IDENTITY(1,1) NOT NULL,    [ItemType] [smallint] NOT NULL,    [Name] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,CONSTRAINT [PK_SalaryItem] PRIMARY KEY CLUSTERED(    [ID] ASC))ALTER TABLE [SalaryItem]  WITH CHECK ADD  CONSTRAINT [FK_SalaryItem_SysSalaryItemTypeMTR] FOREIGN KEY([ItemType])REFERENCES [SysSalaryItemTypeMTR] ([ID])CREATE TABLE [Salary](    [ID] [int] Identity(1,1)NOT NULL,    [EmployeeID] [int] NOT NULL,    [SalaryMonth] [datetime] NULL,    [SalaryItemID] [smallint] NOT NULL,    [Amount] [money] NULL,CONSTRAINT [PK_Salary] PRIMARY KEY CLUSTERED(    [ID] ASC))ALTER TABLE [Salary]  WITH CHECK ADD  CONSTRAINT [FK_Salary_Employee] FOREIGN KEY([EmployeeID])REFERENCES [Employee] ([ID])ALTER TABLE [Salary]  WITH CHECK ADD  CONSTRAINT [FK_Salary_SalaryItem] FOREIGN KEY([SalaryItemID])REFERENCES [SalaryItem] ([ID])Create Table Formulary(    ID int Identity(1,1) Not Null,    SalaryItemID Smallint Not Null,    Definition nvarchar(4000) Null,    Sequence smallint Null,    EffectiveDate datetime Null,    ExpiryDate datetime Null,    Constraint PK_Formulary Primary Key(ID Asc),    Constraint FK_Formulary_SalaryItem Foreign Key (SalaryItemID) References SalaryItem(ID))CREATE NONCLUSTERED INDEX [IX_Employee_EmployeeNo] ON [Employee](    [EmployeeNo] ASC)CREATE NONCLUSTERED INDEX [IX_Formulary_SalaryItemID] ON [Formulary](    [SalaryItemID] ASC)CREATE NONCLUSTERED INDEX [IX_Salary_EmployeeID] ON [Salary](    [EmployeeID] ASC)CREATE NONCLUSTERED INDEX [IX_Salary_SalaryMonth_EmployeeID] ON [Salary](    [SalaryMonth] ASC,    [EmployeeID] ASC)插入测试数据:Use testGoIf Not Exists(Select 1 From SysSalaryItemTypeMTR)    Insert Into SysSalaryItemTypeMTR(Name)        Select N'上月项' Union All        Select N'固定项' Union All        Select N'输入项' Union All        Select N'公式项' Union All        Select N'文本项'If Not Exists(Select 1 From SalaryItem)    Insert Into SalaryItem(ItemType,Name)        Select 2,N'基本工资' Union All        Select 3,N'其他扣款' Union All        Select 3,N'岗位津贴' Union All        Select 3,N'技术津贴' Union All        Select 3,N'住宿费'     Union All        Select 1,N'上月余额' Union All        Select 4,N'应得工资' Union All        Select 4,N'本月余额' Union All        Select 4,N'实得工资'If Not Exists(Select 1 From Formulary)    Insert Into Formulary(SalaryItemID,Definition,Sequence,EffectiveDate,ExpiryDate)        Select 1,N'Isnull([1],0)',1,'20090101','21001231' Union ALl        Select 2,N'Isnull([2],0)',2,'20090101','21001231' Union ALl        Select 3,N'Isnull([3],0)',3,'20090101','21001231' Union ALl        Select 4,N'Isnull([4],0)',4,'20090101','21001231' Union ALl        Select 5,N'Isnull([5],0)',5,'20090101','21001231' Union ALl        Select 6,N'Isnull([8],0)',6,'20090101','21001231' Union ALl        Select 7,N'Isnull([1],0)+Isnull([2],0)+Isnull([3],0)+Isnull([4],0)+Isnull([5],0)+Isnull([6],0)',7,'20090101','21001231' Union ALl        Select 8,N'Case Convert(char(6),DimissionDate,112)+''01'' When SalaryMonth Then 0 Else Isnull([7],0)%10 End ',8,'20090101','21001231' Union ALl        Select 9,N'Case Convert(char(6),DimissionDate,112)+''01'' When SalaryMonth Then Isnull([7],0) Else Isnull([7],0)-Isnull([8],0) End',9,'20090101','21001231'If Not Exists(Select 1 From Employee)    Insert Into Employee(EmployeeNo,Name,Sex,Department,Position,JoinDate,DimissionDate)        Select N'N0001',N'A1',N'男',N'Dep1',N'Pos1','20080101',Null Union All        Select N'N0002',N'A2',N'女',N'Dep2',N'Pos2','20080101','20090514' Union All        Select N'N0003',N'A3',N'男',N'Dep3',N'Pos3','20080101',NullIf Not Exists(Select 1 From Salary)    Insert Into Salary(EmployeeID,SalaryMonth,SalaryItemID,Amount)        Select 1,'20090401',1,1000 Union All        Select 2,'20090401',1,2000 Union All        Select 3,'20090401',1,3000 Union All        Select 1,'20090401',2,-10 Union All        Select 2,'20090401',2,-20 Union All        Select 3,'20090401',2,-30 Union All        Select 1,'20090401',3,0 Union All        Select 2,'20090401',3,0 Union All        Select 3,'20090401',3,0 Union All        Select 1,'20090401',4,105 Union All        Select 2,'20090401',4,0 Union All        Select 3,'20090401',4,107 Union All        Select 1,'20090401',5,-60 Union All        Select 2,'20090401',5,-60 Union All        Select 3,'20090401',5,-60 Union All        Select 1,'20090401',6,0 Union All        Select 2,'20090401',6,0 Union All        Select 3,'20090401',6,0 Union All        Select 1,'20090401',7,0 Union All        Select 2,'20090401',7,0 Union All        Select 3,'20090401',7,0 Union All        Select 1,'20090401',8,0 Union All        Select 2,'20090401',8,0 Union All        Select 3,'20090401',8,0 Union All        Select 1,'20090401',9,0 Union All        Select 2,'20090401',9,0 Union All        Select 3,'20090401',9,0 Union All        Select 1,'20090501',1,1000 Union All        Select 2,'20090501',1,2000 Union All        Select 3,'20090501',1,3000 Union All        Select 1,'20090501',2,-25 Union All        Select 2,'20090501',2,-25 Union All        Select 3,'20090501',2,-25 Union All        Select 1,'20090501',3,20 Union All        Select 2,'20090501',3,10 Union All        Select 3,'20090501',3,10 Union All        Select 1,'20090501',4,150 Union All        Select 2,'20090501',4,20 Union All        Select 3,'20090501',4,150 Union All        Select 1,'20090501',5,-62 Union All        Select 2,'20090501',5,-62 Union All        Select 3,'20090501',5,-62 Union All        Select 1,'20090501',6,0 Union All        Select 2,'20090501',6,0 Union All        Select 3,'20090501',6,0 Union All        Select 1,'20090501',7,0 Union All        Select 2,'20090501',7,0 Union All        Select 3,'20090501',7,0 Union All        Select 1,'20090501',8,0 Union All        Select 2,'20090501',8,0 Union All        Select 3,'20090501',8,0 Union All        Select 1,'20090501',9,0 Union All        Select 2,'20090501',9,0 Union All        Select 3,'20090501',9,0Go

建测试存储过程:


Use testGOIf object_id('up_SalarySUM') Is Not Null    Drop Proc up_SalarySUMGoCreate Proc up_SalarySUM(    @SalaryMonth datetime)AsSet Nocount OnDeclare @SalaryItemID nvarchar(50),        @ItemType smallint,        @Sql nvarchar(4000),        @Definition nvarchar(4000),        @Cols nvarchar(4000)If object_id('tempdb..#Salary') Is Not Null    Drop Table #SalaryCreate Table #Salary(EmployeeID int,DimissionDate datetime,SalaryMonth datetime)Select @Cols=Isnull(@Cols+',','')+Rtrim(Quotename(a.ID))        From SalaryItem As a            Inner Join Formulary As b On b.SalaryItemID=a.ID        Where b.EffectiveDate<=@SalaryMonth                And b.ExpiryDate>@SalaryMonthSet @Sql=N'Alter Table #Salary Add '+Replace(@Cols,',',' money,')+' money'Exec sp_executesql @SqlSet @Sql=N';With CTE_Salary As(    Select a.EmployeeID,b.DimissionDate,SalaryMonth,a.SalaryItemID,a.Amount        From Salary As a            Inner Join Employee As b On b.ID=a.EmployeeID        Where SalaryMonth In(@SalaryMonth,Dateadd(month,-1,@SalaryMonth)))Insert Into #Salary    Select *        From  CTE_Salary        Pivot(Max(Amount) For SalaryItemID In('+@Cols+')) As b'Exec sp_executesql @Sql,N'@SalaryMonth datetime',@SalaryMonthDeclare Cur_SalaryItem Cursor For    Select Quotename(a.ID) As ID,a.ItemType,b.Definition         From SalaryItem As a            Inner Join Formulary As b On b.SalaryItemID=a.ID        Where b.EffectiveDate<=@SalaryMonth                And b.ExpiryDate>@SalaryMonth                And a.ItemType In(1,4)        Order By b.Sequence    For Read OnlyOpen Cur_SalaryItemFetch Next From Cur_SalaryItem Into @SalaryItemID,@ItemType,@DefinitionWhile @@Fetch_status=0Begin    If @ItemType=4 --本月可计算的工资项        Set @sql='Update #Salary Set '+@SalaryItemID+'='+@Definition +' Where SalaryMonth=@SalaryMonth'    Else            --计算上月工资项        Set @sql='Update a  Set a.'+@SalaryItemID+'=(Select '+@Definition +' From #Salary Where EmployeeID=a.EmployeeID And SalaryMonth=Dateadd(Month,-1,a.SalaryMonth)) From #Salary As a Where SalaryMonth=@SalaryMonth'    Exec sp_executesql @sql,N'@SalaryMonth datetime',@SalaryMonth    Fetch Next From Cur_SalaryItem Into @SalaryItemID,@ItemType,@DefinitionEndClose Cur_SalaryItemDeallocate Cur_SalaryItemSet @sql=(N';With CTE_Salary As(    Select * From #Salary Unpivot(Amount For SalaryItemID In('+@Cols+')) As up Where SalaryMonth=@SalaryMonth)Update a    Set a.Amount=b.Amount    From Salary As a        Inner Join CTE_Salary As b On b.SalaryMonth=a.SalaryMonth                And b.EmployeeID=a.EmployeeID                And b.SalaryItemID=a.SalaryItemID')Exec sp_executesql @sql,N'@SalaryMonth datetime',@SalaryMonthDrop Table #SalaryGo

--执行工资计算

Exec up_SalarySUM '20090401'Exec up_SalarySUM '20090501'Go

---查看计算结果


Declare @Cols nvarchar(4000),        @SalaryMonth datetime,        @Sql nvarchar(4000)Set @SalaryMonth='20090501'Select @Cols=Isnull(@Cols+',','')+Rtrim(Quotename(a.Name))        From SalaryItem As a            Inner Join Formulary As b On b.SalaryItemID=a.ID        Where b.EffectiveDate<=@SalaryMonth                And b.ExpiryDate>@SalaryMonthSet @Sql=N';With CTE_Salary As(    Select a.EmployeeID,b.DimissionDate,SalaryMonth,c.Name As SalaryItem,a.Amount        From Salary As a            Inner Join Employee As b On b.ID=a.EmployeeID            Inner Join SalaryItem As c On c.ID=a.SalaryItemID        Where SalaryMonth=@SalaryMonth)    Select *        From  CTE_Salary        Pivot(Max(Amount) For SalaryItem In('+@Cols+')) As b'Exec sp_executesql @Sql,N'@SalaryMonth datetime',@SalaryMonthGo

Demo效果如图:

SQL server 自定义工资公式设计的更多相关文章

  1. sql server 自定义函数的使用

    sql server 自定义函数的使用 自定义函数 用户定义自定义函数像内置函数一样返回标量值,也可以将结果集用表格变量返回 用户自定义函数的类型: 标量函数:返回一个标量值 表格值函数{内联表格值函 ...

  2. SQL Server:OA权限管理设计的实现 下

    SQL Server:OA权限管理设计的实现 下   OA系统权限管理设计方案     不同职责的人员,对于系统操作的权限应该是不同的.优秀的业务系统,这是最基本的功能.     可以对“组”进行权限 ...

  3. 13、SQL Server 自定义函数

    SQL Server 自定义函数 在SQL Server中不仅可以使用系统函数(如:聚合函数,字符串函数,时间日期函数等)还可以根据需要自定义函数. 自定义函数分为标量值函数和表值函数. 其中,标量值 ...

  4. SQL Server 自定义函数(Function)——参数默认值

    sql server 自定义函数分为三种类型:标量函数(Scalar Function).内嵌表值函数(Inline Function).多声明表值函数(Multi-Statement Functio ...

  5. 也来谈谈SQL SERVER 自定义函数~

    在使用SQL SERVER 数据库的时候,函数大家都应该用过,简单的比如 系统聚合函数 Sum(),Max() 等等.但是一些初学者编写自定义函数的时候,经常问起什么是表值函数,什么是标量值函数. 表 ...

  6. SQL Server自定义函数( 转载于51CTO )

    用户自定义函数自定义函数不能执行一系列改变数据库状态的操作,可以像系统函数在查询或存储过程等的程序中使用,也可以像相信过程一样能过 execute 命令来执行.自定义函数中存储了一个 Transact ...

  7. 通过SQL Server自定义数据类型实现导入数据

    写在前面 在看同事写的代码时看到了SQL Server中可以自定义数据类型,而且定义的是DataTable类型的数据类型. 后我想起了以前我们导入数据时要么是循环insert写入,要么是SqlBulk ...

  8. SQL Server 自定义聚合函数

    说明:本文依据网络转载整理而成,因为时间关系,其中原理暂时并未深入研究,只是整理备份留个记录而已. 目标:在SQL Server中自定义聚合函数,在Group BY语句中 ,不是单纯的SUM和MAX等 ...

  9. Sql Server 自定义数据类型

    SQLServer 提供了 25 种基本数据类型: ·Binary [(n)]  二进制数据 既可以是固定长度的(Binary),也可以是变长度的.其中,n 的取值范围是从 1 到 8000.其存储窨 ...

  10. SQL Server 自定义快捷键

    SQL Server程序员经常要在SSMS(SQL Server Management Studio)或查询分析器(2000以前)中编写T-SQL代码.以下几个技巧,可以提升工作效率. 以下说明以SS ...

随机推荐

  1. 记录--服务端推送到Web前端有哪几种方式?

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 这个问题? 这个问题一般会出现在面试题里面,然后回答一些诸如轮询.WebSocket之类的答案.当然,实际开发中,也会遇到类似别人给你赞了 ...

  2. 记录--Cesium+Vue实战教程——地图导航

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 项目效果 我们今天要实现的是一个路径规划的功能,有两个输入框.输入起点终点,然后查询,得到规划的路径,效果如下: 我们会用到以下库: Ax ...

  3. Bad magic number for central directory

    Bad magic number for central directory 运行代码输出如下bug: File "/home/a/Prediction/Predict_Models.py& ...

  4. FPGA中与时序有关的概念

    FPGA中与时序有关的概念 一.时序分析 时序分析是对整个时序进行分析的操作.作用就是了解设计的时序性能,一般而言就是最大时钟频率.时钟频率越高,设计的工作速度越快(忽略设计实现方法的不同导致的效率提 ...

  5. proteus的C51仿真

    Proteus的C51仿真 1.实验原理 Proteus是对C51仿真效果比较好的软件了,可以利用丰富的数字资源的外设实现比较接近实际的设计.仿真方法也比较简单,不需要下载,只需要将仿真文件导出到器件 ...

  6. ssh连接相关工具下载地址

    1.Finalshell 下载地址: http://www.hostbuf.com/t/988.html 2.xShell https://www.xshell.com/zh/xshell/ 3.pu ...

  7. 表的唯一约束的作用 KingbaseES VS Oracle

    背景 演示唯一约束怎样创建.删除.禁用和使用唯一性约束,已经多种数据库的差异. 什么是唯一约束 唯一性约束指表中一个字段或者多个字段联合起来可以唯一标识一条记录的约束, 字段中,可以包括空值. 唯一性 ...

  8. 关于JDK21控制台字符集编码问题

    关于JDK21控制台字符集编码问题 前言: 某日尝试JDK21,idea控制台字符集编码一直乱码,后将idea所有能配置UTF-8的配置都配了一遍,无果,后搜索JDK21字符集编码相关后解决 1.配置 ...

  9. #floyd,斜率#洛谷 1354 房间最短路问题

    题目 在一个长宽均为10,入口出口分别为(0,5),(10,5)的房间里有几堵墙, 每堵墙上有两个缺口,求入口到出口的最短路径. 分析 暴力建图,判断两个点是否有墙堵住, 可以求斜率然后判断所交点不能 ...

  10. 解析 Go 编程语言数据类型:bool、整数、浮点数和字符串详细介绍

    数据类型 数据类型是编程中的重要概念.数据类型指定了变量值的大小和类型.Go是静态类型的,这意味着一旦变量类型被定义,它只能存储该类型的数据. 基本数据类型 Go 有三种基本数据类型: bool:表示 ...