自定义工资公式设计(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 , 1 Not   Null ,
    EmployeeNo 
nvarchar ( 50 Not   Null ,
    Name 
nvarchar ( 50 Not   Null ,
    Sex 
nchar ( 1 Not   Null ,
    Department 
int   Not   Null ,
    Position 
nvarchar ( 50 Null ,
    OutDutyDate 
datetime ,
    
Constraint  PK_Employee_ID  Primary   Key (ID  Asc )
)
Create   Table  SalaryItemMTR
(
    ID 
int   Identity ( 1 , 1 Not   Null ,
    Name 
nvarchar ( 50 Null ,
    EffectiveDate 
datetime ,
    ExpiryDate 
datetime ,
    
Constraint  PK_SalaryItemMTR_ID  Primary   Key (ID  Asc )
)
Create   Table  Salary
(
    ID 
int   Identity ( 1 , 1 Not   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 , 1 Not   Null ,
    Item 
int   Not   Null ,
    Computable 
bit   Null ,
    
Constraint  PK_SysExpressionsMTR_ID  Primary   Key (ID  Asc ),
)
Create   Table  Expressions
(
    ID 
int   Identity ( 1 , 1 Not   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




你可能感兴趣的:(sql2000)