我对存储过程的体验有限,我希望这能解决我的工资问题。此外,对于我试图完成的事情,存储过程可能不是最好的答案。
我正在尝试使用Payroll函数,其中存储过程的目标是获取给定工资核算期间的数据,对第一个返回的员工进行数学运算,输出计算结果,然后移至下一个。让我解释一下......
根据存储过程的付款期ID,我希望它能够执行以下操作:
选择该期间的员工,添加他的工作总时数,然后添加员工总佣金(以较大者为准) - 返回该值(以及总计 - 例如总小时数和总佣金数) - 然后转到下一位员工,直到完成。
数据的布局如下:
工资核算期间表 PayrollID,DateBegin,DateEnd 存储过程在开始时被赋予工资单ID(作为QueryString),因此我必须采用相应的DateBegin& DateEnd数据,并从EmployeeTimeTable中获取DateTimeIn和DateTimeOut以获取相应的出勤记录。
PayrollID - 付款期的ID DateBegin - 支付期的开始日期 DateEnd - 支付期的结束日期。
员工时间表 EmployeeID,DateTimeIn,DateTimeOut,HourlyRate,CalculatedHours,AmountPaid - 每个工作日都有一个实例,因此存储过程将计算当天的工作时间。
EmployeeID - 与此有关的记录的员工的身份。
DateTimeIn - 员工打入的日期和时间。
DateTimeOut - 员工打孔的日期和时间
HourlyRate - 员工每小时支付的货币汇率
CalculatedHours - 此记录的工作小时数
AmountPaid - Simply HourlyRate x CalculatedHours。
佣金表 EmployeeID,PayrollID,AmountPaid - 每笔销售所获得的每个“佣金”都有一条记录。
EmployeeID - 与此有关的记录的员工的身份。
PayrollID - 支付期的ID
AmountPaid - 此记录所赚取的佣金金额。
所以我的问题是 - 我如何创建描述的功能?它甚至可能吗?这需要奇迹才能完成!?或者我有更好的方法来解决这个问题吗?
另外,最后这理论上会输出到WebForm GridView。
答案 0 :(得分:1)
@Damien_The_Unbeliever在他的建议中是正确的。
但是,我认为您有3种选择:
我在路上,并且没有可以使用的SQL Server实例,因此下面的示例可能包含一些语法错误,但选项3的工作原理如下:
create proc calculatePaySlipForPeriod @periodID int
as
begin
create table #results
(emp_id int,
emp_name varchar(255),
commission_earnt money,
labour_earnt money,
amount_to_pay money)
insert into #results
select emp_id
from employee_time
where timeIn between (select dateBegin from PayrollPeriod where PayrollID = @periodID)
and (select dateEnd from PayrollPeriod where PayrollID = @periodID)
insert into #results
select emp_id
from Commission
where payrollID = @periodID
and emp_id not in
(select emp_id from #results)
/** We now have all the employees in the table, so we can populate their earnings **/
update #results
set labour_earnt_money = sum(AmountPaid)
from #results r,
employee_time et
where r.emp_id = et.emp_id
and timeIn between (select dateBegin from PayrollPeriod where PayrollID = @periodID)
and (select dateEnd from PayrollPeriod where PayrollID = @periodID)
update #results
set commission_earnt = sum(AmountPaid)
from #results r,
Commission c
where r.emp_id = c.emp_id
and c.payroll_id = @periodID
update #results
set amount_to_pay = commission_earnt
where commission_earnt > labour_earnt
update #results
set amount_to_pay = labour_earnt
where labour_earnt >= commission_earnt
/** We now have all the data populated, so we return the table to the front end.
select * from #results
/** no need to explicitly drop the table, happens automatically at the end of the proc.
end
这是大纲 - 您可能需要处理日期/时间的怪异(在运营期间操作员开始或结束时计算的班次?我假设开始)。
通过逐步建立结果,您可以轻松地计算出正在发生的事情;要进行调试,您可以在执行期间选择*形成临时表。
答案 1 :(得分:1)
假设EmployeeTime表看起来像这样:
CREATE TABLE EmployeeTime (
EmployeeID int not null,
DateTimeIn datetime not null,
DateTimeOut datetime not null,
HourlyRate decimal(10,2) not null,
HoursWorked as (CONVERT(int,DATEDIFF(minute,DateTimeIn,DateTimeOut)/15.0)+1)/4.0,
AmountPaid as (CONVERT(int,DATEDIFF(minute,DateTimeIn,DateTimeOut)/15.0)+1)/4.0 * HourlyRate
)
(不幸的是,您无法基于另一个计算列构建一个计算列。但是,您可以将公式(CONVERT(int,DATEDIFF(minute,DateTimeIn,DateTimeOut)/15.0)+1)/4.0
移动到用户定义的函数中)
然后你会写一个如下所示的查询:
;WITH PayrollPayments as (
SELECT PayrollID,EmployeeID, SUM(HoursWorked) as HoursWorkedTotal,SUM(AmountPaid) as TotalPay,0 as Commission from EmployeeTime et inner join Payroll p on p.DateBegin < et.DateTimeOn and p.DateEnd > et.DateTimeOut GROUP BY PayrollID,EmployeeID
UNION ALL
SELECT PayrollID,EmployeeID,0,SUM(AmountPaid) as TotalPay,1 from Commissions
)
SELECT PayrollID,EmployeeID,MAX(HoursWorkedTotal) as TotalHours,MAX(TotalPay) as MaxPay,MAX(CASE WHEN Commission=0 THEN TotalPay END) as TotalPayment,MAX(CASE WHEN Commission=1 THEN TotalPay END) as TotalCommission
FROM PayrollPayments
WHERE
PayrollID = @PayrollID
如果您的EmployeeTime表看起来不像上面那样,并且您无法更改现有的EmployeeTime表,则始终可以在上面的查询中创建一个公用表表达式(类似于PayrollPayments
)工作小时数/金额支付计算优先。