自定义工资公式设计(SQL2000版V1.0)












Use Test
Go
Set Nocount On

/*自定義公式測試2000版V1.0 Andy 2009-7-20*/
If object_id('Expressions'Is Not Null
    
Drop Table Expressions

If object_id('ExpressionsMTR'Is Not Null
    
Drop Table ExpressionsMTR

If object_id('Salary'Is Not Null
    
Drop Table Salary

If object_id('Employee'Is Not Null
    
Drop Table Employee

If object_id('SysExpressionsMTR'Is Not Null
    
Drop Table SysExpressionsMTR

If object_id('SalaryItemMTR'Is Not Null
    
Drop Table SalaryItemMTR
Go


Create Table Employee
(
    ID 
int Identity(1,1Not Null,
    EmployeeNo 
nvarchar(50Not Null,
    Name 
nvarchar(50Not Null,
    Sex 
nchar(1Not Null,
    Department 
int Not Null,
    Position 
nvarchar(50Null,
    OutDutyDate 
datetime,
    
Constraint PK_Employee_ID Primary Key(ID Asc)
)
Create Table SalaryItemMTR
(
    ID 
int Identity(1,1Not Null,
    Name 
nvarchar(50Null,
    EffectiveDate 
datetime,
    ExpiryDate 
datetime,
    
Constraint PK_SalaryItemMTR_ID Primary Key(ID Asc)
)
Create Table Salary
(
    ID 
int Identity(1,1Not Null,
    EmployeeID 
int Not Null,
    Period 
datetime Not Null,
    SalaryItem 
int Not Null,
    Amount 
money,
    
Constraint PK_Salary_ID Primary Key(ID Asc),
    
COnstraint FK_Salary_EmployeeID Foreign Key(EmployeeiD) References Employee(ID),
    
COnstraint FK_Salary_SalaryItem Foreign Key(SalaryItem) References SalaryItemMTR(ID)
)

Create Table ExpressionsMTR
(
    ID 
int Identity(1,1Not Null,
    Item 
int Not Null,
    Computable 
bit Null,
    
Constraint PK_SysExpressionsMTR_ID Primary Key(ID Asc),
)
Create Table Expressions
(
    ID 
int Identity(1,1Not Null,
    ExpressionsMTRID 
int Not Null,
    Seq 
int ,
    Definition 
nvarchar(2048),
    EffectiveDate 
datetime,
    ExpiryDate 
datetime,
    
Constraint PK_Expressions_ID Primary Key(ID Asc),
    
Constraint FK_Expressions_ExpressionsMTRID Foreign Key (ExpressionsMTRID) References ExpressionsMTR(ID)
)

GO
Insert Into Employee (EmployeeNo,Name,Sex,Department,Position,OutDutyDate)
    
Select N'N0001',N'張11',N'',1,N'經理','20080125' Union All
    
Select N'N0002',N'李12',N'',1,N'助理',Null Union All
    
Select N'N0003',N'黃22',N'',3,N'技師',Null Union All
    
Select N'N0004',N'劉33',N'',4,N'保安',Null Union All
    
Select N'N0005',N'黃32',N'',6,N'廚師',Null 


Insert Into SalaryItemMTR (Name,EffectiveDate,ExpiryDate)
    
Select N'底薪','20080101','30001231' Union All
    
Select N'平日加班費','20080101','30001231' Union All
    
Select N'周末加班費','20080101','30001231' Union All
    
Select N'技術津貼','20080101','30001231' Union All
    
Select N'崗位津貼','20080101','30001231' Union All
    
Select N'上月余額','20080101','30001231' Union All
    
Select N'應得工資','20080101','30001231' Union All
    
Select N'本月余額','20080101','30001231' Union All
    
Select N'實際工資','20080101','30001231' 

Insert Into Salary (EmployeeID,Period,SalaryItem,Amount)
    
Select 1,'20080101',1,5000 Union All
    
Select 1,'20080101',2,0 Union All
    
Select 1,'20080101',3,0 Union All
    
Select 1,'20080101',4,0 Union All
    
Select 1,'20080101',5,2602 Union All
    
Select 1,'20080101',6,18.65 Union All
    
Select 1,'20080101',7,0 Union All
    
Select 1,'20080101',8,0 Union All
    
Select 1,'20080101',9,0 Union All
    
Select 2,'20080101',1,3500 Union All
    
Select 2,'20080101',2,300 Union All
    
Select 2,'20080101',3,250 Union All
    
Select 2,'20080101',4,0 Union All
    
Select 2,'20080101',5,200 Union All
    
Select 2,'20080101',6,6.30 Union All
    
Select 2,'20080101',7,0 Union All
    
Select 2,'20080101',8,0 Union All
    
Select 2,'20080101',9,0 

Insert Into ExpressionsMTR (Item,Computable)
    
Select 1,1 Union All
    
Select 2,1 Union All
    
Select 3,1 Union All
    
Select 4,1 Union All
    
Select 5,1 Union All
    
Select 6,1 Union All
    
Select 7,1 Union All
    
Select 8,1 Union All
    
Select 9,1 

Insert Into Expressions (ExpressionsMTRID,Seq,Definition,EffectiveDate,ExpiryDate)
    
Select 1,1,N'Isnull([1],0)','20080101','30001231' Union All
    
Select 2,2,N'Isnull([2],0)','20080101','30001231' Union All
    
Select 3,3,N'Isnull([3],0)','20080101','30001231' Union All
    
Select 4,4,N'Isnull([4],0)','20080101','30001231' Union All
    
Select 5,5,N'Isnull([5],0)','20080101','30001231' Union All
    
Select 6,6,N'Isnull([6],0)','20080101','30001231' Union All
    
Select 7,7,N'([1]+[2]+[3]+[4]+[5]+[6])','20080101','30001231' Union All
    
Select 8,8,N'Case When Period=Convert(char(6),OutDutyDate,112)+''01'' Then 0 Else Cast(Round([7],0,1) As int)%10+[7]-Round([7],0,1) End','20080101','30001231' Union All
    
Select 9,9,N'[7]-[8]','20080101','30001231' 

/*
1.在MSSQL2000中使用"%"取模運算符的時候,要求被除數/除數必須是int類型,到了MSSQL2005就有很大的改進,不用轉換成int,只要是數值就可以。

2.這里使用到的Cast()隱藏一些知識, 

表達式            四舍五入(Y/N)
--------------------------------------------
Cast(字段名 As int)         N
Cast(直接寫的數值 As int)      N
Cast(變量 As int)         Y

這里為了能明確表明不要四舍五入,使用了Round()函數。


*/

Go
If object_id('uSalaryForExpressionsByPeriod'Is Not Null
    
Drop Proc uSalaryForExpressionsByPeriod
Go
Create Proc uSalaryForExpressionsByPeriod
(
    
@Period datetime
)
As
Set Nocount On
Declare    @Sql nvarchar(4000),
        
@Columns nvarchar(4000),
        
@StrPeriod nvarchar(8),
        
@UpdateSql nvarchar(4000),
        
@PivotSql nvarchar(4000),
        
@UnpivotSql nvarchar(4000)

Set @StrPeriod=Convert(char(8),@Period,112)

If object_id('tempdb..#Salary'Is Not Null
    
Drop Table #Salary

Create Table #Salary(Period datetime,EmployeeID int Primary Key,EmployeeNo nvarchar(50),Name nvarchar(50),Department int,Position nvarchar(50),OutDutyDate datetime)

Select    @Columns=Isnull(@Columns+',',''+Quotename(Item),
        
@UpdateSql=Isnull(@UpdateSql+Char(13)+Char(10),'')+'Update #Salary Set '+Quotename(a.Item)+'='+b.Definition,
        
@PivotSql=Isnull(@PivotSql,'')+',Sum(Case SalaryItem When '+Rtrim(a.Item)+' Then Amount Else 0 End) As '+Quotename(a.Item),
        
@UnpivotSql=Isnull(@UnpivotSql+ ' Union All ','')+'Select EmployeeID,'+Rtrim(a.Item)+' As SalaryItem,Convert(money,'+Quotename(a.Item)+') As Amount  From #Salary'
    
From ExpressionsMTR As a
        
Inner Join Expressions As b On b.ExpressionsMTRID =a.ID
    
Where b.EffectiveDate<=@Period
            
And b.ExpiryDate>@Period


/*
注:

@PivotSql賦值過程的Sum()寫法
在MSSQL2005版本中使用Pivot方法,可以使用Max()函數,在2000版中要特別小心,這里要使用Sum()函數。因為,當工資項目出現<0的數據時候,使用Max()就錯誤了。
如果非要使用Max(),那樣需要這樣寫:

@PivotSql=Isnull(@PivotSql,'')+',Sum(Case SalaryItem When '+Rtrim(a.Item)+' Then Amount Else 0 End) As '+Quotename(a.Item),


*/

Set @Sql='Alter Table #Salary Add '+Replace(@Columns,',',' money,')+' Money'

Exec(@Sql)

Insert Into #Salary
    
Exec(N'

    Select a.Period,a.EmployeeID,b.EmployeeNo,b.Name,b.Department,b.Position,b.OutDutyDate
'+@PivotSql+'
        From Salary As a
            Inner Join Employee As b On b.ID=a.EmployeeID
        Where a.Period=
'''+@strPeriod+'''
        Group By a.Period,a.EmployeeID,b.EmployeeNo,b.Name,b.Department,b.Position,b.OutDutyDate
    
')



Exec(@UpdateSql)


Exec (N'
Update a
    Set a.Amount=b.Amount
    From Salary As a
        Inner Join (
'+@UnpivotSql+') As b On b.EmployeeID=a.EmployeeID And b.SalaryItem=a.SalaryItem
    Where a.Period=
'''+@strPeriod+'''
')
Go


--調用
Exec uSalaryForExpressionsByPeriod '20080101'

--Debug
Declare @Period datetime,
        
@Sql nvarchar(4000),
        
@PivotSql nvarchar(4000)

Set @Period='20080101'

Select     @PivotSql=Isnull(@PivotSql,'')+',Sum(Case c.name When '''+Rtrim(Name)+''' Then a.Amount Else 0 End) As '+Quotename(Name)
    
From SalaryItemMTR 
    
Where EffectiveDate<=@Period 
            
And ExpiryDate>@Period

Set @Sql=(N'
    Select a.Period,a.EmployeeID,b.EmployeeNo,b.Name,b.Department,b.Position,b.OutDutyDate
'+@PivotSql+'
        From Salary As a
            Inner Join Employee As b On b.ID=a.EmployeeID
            Inner Join SalaryItemMTR As c On c.ID=a.SalaryItem
        Where Period=@Period
        Group By a.Period,a.EmployeeID,b.EmployeeNo,b.Name,b.Department,b.Position,b.OutDutyDate
        

')

Exec sp_executesql @Sql,N'@Period datetime',@Period




原文地址:https://www.cnblogs.com/wghao/p/1547413.html